diff --git a/include/libyuv/row.h b/include/libyuv/row.h index 8f920f202..67eb20cef 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -137,6 +137,8 @@ extern "C" { #define HAS_NV21TORGB24ROW_AVX2 #define HAS_SPLITUVROW_AVX2 #define HAS_UYVYTOARGBROW_AVX2 +#define HAS_UYVYTOUV422ROW_AVX2 +#define HAS_UYVYTOUVROW_AVX2 #define HAS_UYVYTOYROW_AVX2 #define HAS_YUY2TOARGBROW_AVX2 #define HAS_YUY2TOUV422ROW_AVX2 @@ -340,8 +342,10 @@ extern "C" { #define HAS_RAWTORGB24ROW_SSSE3 #define HAS_ARGBALPHABLENDROW_SSSE3 #define HAS_ARGBORROW_SSE2 +#define HAS_BLENDPLANEROW_SSSE3 #define HAS_MIRRORSPLITUVROW_SSSE3 #if defined(VISUALC_HAS_AVX2) +#define HAS_BLENDPLANEROW_AVX2 #define HAS_RAWTORGB24ROW_AVX2 #define HAS_RAWTOARGBROW_AVX2 #define HAS_I422TORGB24ROW_AVX2 @@ -3004,14 +3008,26 @@ void MirrorSplitUVRow_NEON(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, int width); +void MirrorSplitUVRow_Any_NEON(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); void MirrorSplitUVRow_LSX(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, int width); +void MirrorSplitUVRow_Any_LSX(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); void MirrorSplitUVRow_LASX(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, int width); +void MirrorSplitUVRow_Any_LASX(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); void MirrorSplitUVRow_C(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, @@ -3337,6 +3353,12 @@ void HalfMergeUVRow_Any_AVX2(const uint8_t* src_u, int src_stride_v, uint8_t* dst_uv, int width); +void HalfMergeUVRow_Any_NEON(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int width); void SplitRGBRow_C(const uint8_t* src_rgb, uint8_t* dst_r, @@ -8234,6 +8256,10 @@ void MirrorRow_Any_WASMSIMD(const uint8_t* src_ptr, void MirrorUVRow_Any_WASMSIMD(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorSplitUVRow_Any_WASMSIMD(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); void SwapUVRow_Any_WASMSIMD(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); diff --git a/include/libyuv/row_sve.h b/include/libyuv/row_sve.h index 7faf57db8..284b37007 100644 --- a/include/libyuv/row_sve.h +++ b/include/libyuv/row_sve.h @@ -439,7 +439,6 @@ static inline void I444ToRGB24Row_SVE_SC( "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV444_SVE_2X I444TORGB_SVE_2X RGBTOARGB8_SVE_2X "st3b {z16.b, z17.b, z18.b}, p1, [%[dst_rgb24]] \n" @@ -453,7 +452,7 @@ static inline void I444ToRGB24Row_SVE_SC( [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } static inline void I400ToARGBRow_SVE_SC(const uint8_t* src_y, @@ -503,7 +502,7 @@ static inline void I400ToARGBRow_SVE_SC(const uint8_t* src_y, [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } static inline void I422ToARGBRow_SVE_SC(const uint8_t* src_y, @@ -536,7 +535,6 @@ static inline void I422ToARGBRow_SVE_SC(const uint8_t* src_y, "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_2X "st4b {z16.b, z17.b, z18.b, z19.b}, p1, [%[dst_argb]] \n" @@ -550,7 +548,7 @@ static inline void I422ToARGBRow_SVE_SC(const uint8_t* src_y, [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } static inline void I422ToRGB24Row_SVE_SC( @@ -583,7 +581,6 @@ static inline void I422ToRGB24Row_SVE_SC( "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_2X "st3b {z16.b, z17.b, z18.b}, p1, [%[dst_argb]] \n" @@ -597,7 +594,7 @@ static inline void I422ToRGB24Row_SVE_SC( [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } #define RGB8TORGB565_SVE_FROM_TOP_2X \ @@ -638,7 +635,6 @@ static inline void I422ToRGB565Row_SVE_SC( "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_TOP_2X RGB8TORGB565_SVE_FROM_TOP_2X @@ -657,7 +653,7 @@ static inline void I422ToRGB565Row_SVE_SC( [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } #define RGB8TOARGB1555_SVE_FROM_TOP_2X \ @@ -701,7 +697,6 @@ static inline void I422ToARGB1555Row_SVE_SC( "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_TOP_2X RGB8TOARGB1555_SVE_FROM_TOP_2X @@ -720,7 +715,7 @@ static inline void I422ToARGB1555Row_SVE_SC( [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } #define RGB8TOARGB4444_SVE_FROM_TOP_2X \ @@ -764,7 +759,6 @@ static inline void I422ToARGB4444Row_SVE_SC( "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV422_SVE_2X I422TORGB_SVE_2X RGBTOARGB8_SVE_TOP_2X RGB8TOARGB4444_SVE_FROM_TOP_2X @@ -783,7 +777,7 @@ static inline void I422ToARGB4444Row_SVE_SC( [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } static inline void I422ToRGBARow_SVE_SC(const uint8_t* src_y, @@ -829,7 +823,7 @@ static inline void I422ToRGBARow_SVE_SC(const uint8_t* src_y, [vl] "=&r"(vl) // %[vl] : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias) // %[kRGBCoeffBias] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } static inline void I422ToAR30Row_SVE_SC(const uint8_t* src_y, @@ -879,7 +873,7 @@ static inline void I422ToAR30Row_SVE_SC(const uint8_t* src_y, : [kUVCoeff] "r"(&yuvconstants->kUVCoeff), // %[kUVCoeff] [kRGBCoeffBias] "r"(&yuvconstants->kRGBCoeffBias), // %[kRGBCoeffBias] [limit] "r"(limit) // %[limit] - : "cc", "memory", YUVTORGB_SVE_REGS); + : "memory", "cc", YUVTORGB_SVE_REGS); } static inline void I422AlphaToARGBRow_SVE_SC( @@ -916,7 +910,6 @@ static inline void I422AlphaToARGBRow_SVE_SC( "b.eq 99f \n" // Calculate a predicate for the final iteration to deal with the tail. - "cnth %[vl] \n" "whilelt p1.b, wzr, %w[width] \n" // READYUV422_SVE_2X "ld1b {z19.b}, p1/z, [%[src_a]] \n" // Alpha @@ -1618,7 +1611,6 @@ static inline void I410AlphaToARGBRow_SVE_SC( asm volatile( "ptrue p0.b \n" // YUVTORGB_SVE_SETUP - "cmp %w[width], %w[vl] \n" "subs %w[width], %w[width], %w[vl] \n" "b.lt 2f \n" diff --git a/include/libyuv/scale_row.h b/include/libyuv/scale_row.h index e81d227d9..871d73dc6 100644 --- a/include/libyuv/scale_row.h +++ b/include/libyuv/scale_row.h @@ -1789,6 +1789,10 @@ void ScaleRowDown2Box_RVV(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst, int dst_width); +void ScaleRowDown2Box_Odd_RVV(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); void ScaleRowDown4_RVV(const uint8_t* src_ptr, ptrdiff_t src_stride, diff --git a/source/compare_gcc.cc b/source/compare_gcc.cc index 5828ceaa7..920401a2e 100644 --- a/source/compare_gcc.cc +++ b/source/compare_gcc.cc @@ -76,14 +76,15 @@ uint32_t HammingDistance_SSE42(const uint8_t* src_a, "+r"(count), // %2 "=&r"(diff) // %3 : - : "cc", "memory", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10"); + : "memory", "cc", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10"); return (uint32_t)(diff); } #endif // HAS_HAMMINGDISTANCE_SSE42 #if defined(HAS_HAMMINGDISTANCE_SSSE3) || defined(HAS_HAMMINGDISTANCE_AVX2) || \ - defined(HAS_HAMMINGDISTANCE_AVX512BW) + defined(HAS_HAMMINGDISTANCE_AVX512BW) || \ + defined(HAS_HAMMINGDISTANCE_AVX512VNNI) static const vec8 kNibbleMask = {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}; static const vec8 kBitCount = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; @@ -144,7 +145,7 @@ uint32_t HammingDistance_SSSE3(const uint8_t* src_a, "=r"(diff) // %3 : "m"(kNibbleMask), // %4 "m"(kBitCount) // %5 - : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"); return diff; @@ -201,12 +202,13 @@ uint32_t HammingDistance_AVX2(const uint8_t* src_a, "=r"(diff) // %3 : "m"(kNibbleMask), // %4 "m"(kBitCount) // %5 - : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); return diff; } #endif // HAS_HAMMINGDISTANCE_AVX2 +#ifdef HAS_SUMSQUAREERROR_SSE2 uint32_t SumSquareError_SSE2(const uint8_t* src_a, const uint8_t* src_b, int count) { @@ -245,9 +247,10 @@ uint32_t SumSquareError_SSE2(const uint8_t* src_a, "+r"(count), // %2 "=r"(sse) // %3 : - : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); return sse; } +#endif // HAS_SUMSQUAREERROR_SSE2 #ifdef HAS_SUMSQUAREERROR_AVX2 uint32_t SumSquareError_AVX2(const uint8_t* src_a, @@ -290,11 +293,12 @@ uint32_t SumSquareError_AVX2(const uint8_t* src_a, "+r"(count), // %2 "=r"(sse) // %3 : - : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); return sse; } #endif // HAS_SUMSQUAREERROR_AVX2 +#ifdef HAS_HASHDJB2_SSE41 static const uvec32 kHash16x33 = {0x92d9e201, 0, 0, 0}; // 33 ^ 16 static const uvec32 kHashMul0 = { 0x0c3525e1, // 33 ^ 15 @@ -371,10 +375,11 @@ uint32_t HashDjb2_SSE41(const uint8_t* src, int count, uint32_t seed) { "m"(kHashMul1), // %6 "m"(kHashMul2), // %7 "m"(kHashMul3) // %8 - : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"); return hash; } +#endif // HAS_HASHDJB2_SSE41 #if defined(HAS_HAMMINGDISTANCE_AVX512BW) || \ defined(HAS_HAMMINGDISTANCE_AVX512VNNI) || \ defined(HAS_SUMSQUAREERROR_AVX512BW) || \ @@ -458,6 +463,7 @@ uint32_t HammingDistance_AVX512BW(const uint8_t* src_a, #ifdef HAS_HAMMINGDISTANCE_AVX512VNNI // Process 64 bytes per loop and the remainder of 1 to 63 bytes with masked // loads that read zeros, accumulating byte popcounts with vpdpbusd. +LIBYUV_TARGET_AVX512VNNI uint32_t HammingDistance_AVX512VNNI(const uint8_t* src_a, const uint8_t* src_b, int count) { @@ -766,7 +772,7 @@ uint32_t HashDjb2_AVX2(const uint8_t* src, int count, uint32_t seed) { : [src] "+r"(src), [count] "+r"(count), [seed] "+r"(seed), [sum] "=&r"(sum) : [tbl] "r"(kHashMulLoHi) - : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); return seed; } #undef HASH32_AVX2 @@ -854,7 +860,7 @@ uint32_t HashDjb2_AVX512BW(const uint8_t* src, int count, uint32_t seed) { : [src] "+r"(src), [width] "+r"(width), [seed] "+r"(seed), [sum] "=&r"(sum) : [tbl] "r"(kHashMulLoHi), [pow_n] "m"(pow_n), [mask] "m"(mask) - : "cc", "memory", "k1", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + : "memory", "cc", "k1", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"); return seed; } diff --git a/source/convert.cc b/source/convert.cc index e76ba7c34..779a71c93 100644 --- a/source/convert.cc +++ b/source/convert.cc @@ -105,10 +105,12 @@ int I420Copy(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -148,10 +150,12 @@ int I010Copy(const uint16_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -193,10 +197,12 @@ static int Planar16bitTo8bit(const uint16_t* src_y, if (height < 0) { height = -height; uv_height = -uv_height; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(uv_height - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(uv_height - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -852,14 +858,17 @@ static int IxxxToPxxx(const uint16_t* src_y, int subsample_x, int subsample_y, int depth) { - if (width <= 0 || height == 0 || height == INT_MIN) { + if ((!src_y && dst_y) || !src_u || !src_v || !dst_uv || width <= 0 || + height == 0 || height == INT_MIN) { return -1; } const int uv_width = SUBSAMPLE(width, subsample_x, subsample_x); const int uv_height = SUBSAMPLE(height, subsample_y, subsample_y); - ConvertToMSBPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height, - depth); + if (dst_y) { + ConvertToMSBPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width, + height, depth); + } MergeUVPlane_16(src_u, src_stride_u, src_v, src_stride_v, dst_uv, dst_stride_uv, uv_width, uv_height, depth); return 0; @@ -912,10 +921,12 @@ int I010ToNV12(const uint16_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -927,6 +938,11 @@ int I010ToNV12(const uint16_t* src_y, } } #endif +#if defined(HAS_CONVERT16TO8ROW_SVE2) + if (TestCpuFlag(kCpuHasSVE2)) { + Convert16To8Row = Convert16To8Row_SVE2; + } +#endif #if defined(HAS_CONVERT16TO8ROW_SME) if (TestCpuFlag(kCpuHasSME)) { Convert16To8Row = Convert16To8Row_SME; @@ -953,6 +969,11 @@ int I010ToNV12(const uint16_t* src_y, Convert16To8Row = Convert16To8Row_AVX512BW; } #endif +#if defined(HAS_CONVERT16TO8ROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + Convert16To8Row = Convert16To8Row_RVV; + } +#endif #if defined(HAS_CONVERT16TO8ROW_HVX) if (TestCpuFlag(kCpuHasHVX)) { Convert16To8Row = Convert16To8Row_HVX; @@ -1195,17 +1216,21 @@ int I422ToI210(const uint8_t* src_y, // Negative height means invert the image. if (height < 0) { height = -height; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } // Convert Y plane. - Convert8To16Plane(src_y, src_stride_y, dst_y, dst_stride_y, 1024, width, - height); + if (dst_y) { + Convert8To16Plane(src_y, src_stride_y, dst_y, dst_stride_y, 1024, width, + height); + } // Convert UV planes. Convert8To16Plane(src_u, src_stride_u, dst_u, dst_stride_u, 1024, halfwidth, height); @@ -1229,7 +1254,8 @@ int I422ToNV21(const uint8_t* src_y, int width, int height) { int r; - if (width <= 0 || height == 0 || height == INT_MIN) { + if ((!src_y && dst_y) || !src_u || !src_v || !dst_vu || width <= 0 || + height == 0 || height == INT_MIN) { return -1; } int halfwidth = (width + 1) >> 1; @@ -1238,10 +1264,12 @@ int I422ToNV21(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -1355,7 +1383,8 @@ int MT2TToP010(const uint8_t* src_y, int dst_stride_uv, int width, int height) { - if (width <= 0 || height == 0 || height == INT_MIN || !src_uv || !dst_uv) { + if ((!src_y && dst_y) || !src_uv || !dst_uv || width <= 0 || height == 0 || + height == INT_MIN) { return -1; } @@ -1674,10 +1703,12 @@ int I444ToNV12(const uint8_t* src_y, // Negative height means invert the image. if (height < 0) { height = -height; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -1729,8 +1760,10 @@ int I400ToI420(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; - src_stride_y = -src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } } if (dst_y) { CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); @@ -1760,8 +1793,10 @@ int I400ToNV21(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; - src_stride_y = -src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } } if (dst_y) { CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); @@ -1795,9 +1830,11 @@ int NV12ToI420(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_uv = src_uv + (ptrdiff_t)(halfheight - 1) * src_stride_uv; - src_stride_y = -src_stride_y; src_stride_uv = -src_stride_uv; } // Coalesce rows. @@ -2473,7 +2510,8 @@ int YUY2ToI420(const uint8_t* src_yuy2, YUY2ToUVRow_C; void (*YUY2ToYRow)(const uint8_t* src_yuy2, uint8_t* dst_y, int width) = YUY2ToYRow_C; - if (width <= 0 || height == 0 || height == INT_MIN) { + if (!src_yuy2 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 || + height == INT_MIN) { return -1; } // Negative height means invert the image. @@ -2585,7 +2623,8 @@ int UYVYToI420(const uint8_t* src_uyvy, UYVYToUVRow_C; void (*UYVYToYRow)(const uint8_t* src_uyvy, uint8_t* dst_y, int width) = UYVYToYRow_C; - if (width <= 0 || height == 0 || height == INT_MIN) { + if (!src_uyvy || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 || + height == INT_MIN) { return -1; } // Negative height means invert the image. @@ -2694,7 +2733,8 @@ int AYUVToNV12(const uint8_t* src_ayuv, uint8_t* dst_uv, int width) = AYUVToUVRow_C; void (*AYUVToYRow)(const uint8_t* src_ayuv, uint8_t* dst_y, int width) = AYUVToYRow_C; - if (width <= 0 || height == 0 || height == INT_MIN) { + if (!src_ayuv || !dst_y || !dst_uv || width <= 0 || height == 0 || + height == INT_MIN) { return -1; } // Negative height means invert the image. @@ -2770,7 +2810,8 @@ int AYUVToNV21(const uint8_t* src_ayuv, uint8_t* dst_vu, int width) = AYUVToVURow_C; void (*AYUVToYRow)(const uint8_t* src_ayuv, uint8_t* dst_y, int width) = AYUVToYRow_C; - if (width <= 0 || height == 0 || height == INT_MIN) { + if (!src_ayuv || !dst_y || !dst_vu || width <= 0 || height == 0 || + height == INT_MIN) { return -1; } // Negative height means invert the image. @@ -4192,6 +4233,16 @@ int RAWToI420(const uint8_t* src_raw, } } #endif +#if defined(HAS_RGBTOUVMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + RGBToUVMatrixRow = RGBToUVMatrixRow_RVV; + } +#endif +#if defined(HAS_RGBTOYMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + RGBToYMatrixRow = RGBToYMatrixRow_RVV; + } +#endif if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 || height == INT_MIN) { @@ -4340,6 +4391,16 @@ int RAWToJ420(const uint8_t* src_raw, } } #endif +#if defined(HAS_RGBTOUVMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + RGBToUVMatrixRow = RGBToUVMatrixRow_RVV; + } +#endif +#if defined(HAS_RGBTOYMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + RGBToYMatrixRow = RGBToYMatrixRow_RVV; + } +#endif if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 || height == INT_MIN) { @@ -5103,9 +5164,11 @@ static int Biplanar16bitTo8bit(const uint16_t* src_y, if (height < 0) { height = -height; uv_height = -uv_height; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_uv = src_uv + (ptrdiff_t)(uv_height - 1) * src_stride_uv; - src_stride_y = -src_stride_y; src_stride_uv = -src_stride_uv; } @@ -5169,10 +5232,12 @@ static int Planar8bitTo8bit(const uint8_t* src_y, if (height < 0) { height = -height; uv_height = -uv_height; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(uv_height - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(uv_height - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } diff --git a/source/convert_argb.cc b/source/convert_argb.cc index 9799e0a79..d69224c16 100644 --- a/source/convert_argb.cc +++ b/source/convert_argb.cc @@ -1141,7 +1141,7 @@ int U010ToAB30(const uint16_t* src_y, int height) { return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u, src_stride_u, dst_ab30, dst_stride_ab30, - &kYuv2020Constants, width, height); + &kYvu2020Constants, width, height); } // Convert 12 bit YUV to ARGB with matrix. @@ -1405,7 +1405,7 @@ int U210ToAB30(const uint16_t* src_y, int height) { return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u, src_stride_u, dst_ab30, dst_stride_ab30, - &kYuv2020Constants, width, height); + &kYvu2020Constants, width, height); } LIBYUV_API @@ -7375,7 +7375,7 @@ int H420ToAR30(const uint8_t* src_y, int height) { return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, dst_ar30, dst_stride_ar30, - &kYvuH709Constants, width, height); + &kYuvH709Constants, width, height); } // Convert I420 to AB30. diff --git a/source/convert_from.cc b/source/convert_from.cc index 6f5853bc2..49402b09d 100644 --- a/source/convert_from.cc +++ b/source/convert_from.cc @@ -398,6 +398,22 @@ int I422ToYUY2(const uint8_t* src_y, } } #endif +#if defined(HAS_I422TOYUY2ROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + I422ToYUY2Row = I422ToYUY2Row_Any_LSX; + if (IS_ALIGNED(width, 16)) { + I422ToYUY2Row = I422ToYUY2Row_LSX; + } + } +#endif +#if defined(HAS_I422TOYUY2ROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + I422ToYUY2Row = I422ToYUY2Row_Any_LASX; + if (IS_ALIGNED(width, 32)) { + I422ToYUY2Row = I422ToYUY2Row_LASX; + } + } +#endif for (y = 0; y < height; ++y) { I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); @@ -678,10 +694,12 @@ int I420ToNV12(const uint8_t* src_y, if (height < 0) { height = -height; halfheight = (height + 1) >> 1; - src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + if (src_y) { + src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u; src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; src_stride_u = -src_stride_u; src_stride_v = -src_stride_v; } @@ -1110,25 +1128,26 @@ int ConvertFromI420(const uint8_t* y, break; case FOURCC_NV12: { int dst_y_stride = dst_sample_stride ? dst_sample_stride : width; + int dst_uv_stride = + dst_sample_stride ? dst_sample_stride : ((width + 1) / 2) * 2; uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height; r = I420ToNV12(y, y_stride, u, u_stride, v, v_stride, dst_sample, - dst_sample_stride ? dst_sample_stride : width, dst_uv, - dst_sample_stride ? dst_sample_stride : width, width, - height); + dst_y_stride, dst_uv, dst_uv_stride, width, height); break; } case FOURCC_NV21: { int dst_y_stride = dst_sample_stride ? dst_sample_stride : width; + int dst_vu_stride = + dst_sample_stride ? dst_sample_stride : ((width + 1) / 2) * 2; uint8_t* dst_vu = dst_sample + (ptrdiff_t)dst_y_stride * abs_height; r = I420ToNV21(y, y_stride, u, u_stride, v, v_stride, dst_sample, - dst_sample_stride ? dst_sample_stride : width, dst_vu, - dst_sample_stride ? dst_sample_stride : width, width, - height); + dst_y_stride, dst_vu, dst_vu_stride, width, height); break; } case FOURCC_NV16: { int dst_y_stride = dst_sample_stride ? dst_sample_stride : width; - int dst_uv_stride = dst_sample_stride ? dst_sample_stride : width; + int dst_uv_stride = + dst_sample_stride ? dst_sample_stride : ((width + 1) / 2) * 2; uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height; int halfwidth = (width + 1) / 2; int halfheight = SUBSAMPLE(height, 1, 1); diff --git a/source/convert_from_argb.cc b/source/convert_from_argb.cc index 8f71a0ad3..f8057535d 100644 --- a/source/convert_from_argb.cc +++ b/source/convert_from_argb.cc @@ -1714,6 +1714,13 @@ int ARGBToI400Matrix(const uint8_t* src_argb, src_argb = src_argb + (ptrdiff_t)(height - 1) * src_stride_argb; src_stride_argb = -src_stride_argb; } + // Coalesce rows. + if (src_stride_argb == width * 4 && dst_stride_y == width && + (ptrdiff_t)width * height <= INT_MAX) { + width *= height; + height = 1; + src_stride_argb = dst_stride_y = 0; + } #if defined(HAS_ARGBTOYMATRIXROW_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYMatrixRow = ARGBToYMatrixRow_Any_SSSE3; @@ -1771,6 +1778,27 @@ int ARGBToI400Matrix(const uint8_t* src_argb, ARGBToYMatrixRow = ARGBToYMatrixRow_SME; } #endif +#if defined(HAS_ARGBTOYMATRIXROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX; + if (IS_ALIGNED(width, 8)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_LSX; + } + } +#endif +#if defined(HAS_ARGBTOYMATRIXROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX; + if (IS_ALIGNED(width, 16)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_LASX; + } + } +#endif +#if defined(HAS_ARGBTOYMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_RVV; + } +#endif #if defined(HAS_ARGBTOYMATRIXROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { ARGBToYMatrixRow = ARGBToYMatrixRow_Any_WASMSIMD; @@ -1877,6 +1905,27 @@ int ARGBToYUY2Matrix(const uint8_t* src_argb, ARGBToYMatrixRow = ARGBToYMatrixRow_SME; } #endif +#if defined(HAS_ARGBTOYMATRIXROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX; + if (IS_ALIGNED(width, 8)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_LSX; + } + } +#endif +#if defined(HAS_ARGBTOYMATRIXROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX; + if (IS_ALIGNED(width, 16)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_LASX; + } + } +#endif +#if defined(HAS_ARGBTOYMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_RVV; + } +#endif #if defined(HAS_ARGBTOYMATRIXROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { ARGBToYMatrixRow = ARGBToYMatrixRow_Any_WASMSIMD; @@ -1951,6 +2000,11 @@ int ARGBToYUY2Matrix(const uint8_t* src_argb, } } #endif +#if defined(HAS_ARGBTOUVMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + ARGBToUVMatrixRow = ARGBToUVMatrixRow_RVV; + } +#endif #if defined(HAS_ARGBTOUVMATRIXROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_WASMSIMD; @@ -1988,6 +2042,22 @@ int ARGBToYUY2Matrix(const uint8_t* src_argb, } } #endif +#if defined(HAS_I422TOYUY2ROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + I422ToYUY2Row = I422ToYUY2Row_Any_LSX; + if (IS_ALIGNED(width, 16)) { + I422ToYUY2Row = I422ToYUY2Row_LSX; + } + } +#endif +#if defined(HAS_I422TOYUY2ROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + I422ToYUY2Row = I422ToYUY2Row_Any_LASX; + if (IS_ALIGNED(width, 32)) { + I422ToYUY2Row = I422ToYUY2Row_LASX; + } + } +#endif { align_buffer_64(row_y, ((width + 63) & ~63) * 2); @@ -2094,6 +2164,27 @@ int ARGBToUYVYMatrix(const uint8_t* src_argb, ARGBToYMatrixRow = ARGBToYMatrixRow_SME; } #endif +#if defined(HAS_ARGBTOYMATRIXROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX; + if (IS_ALIGNED(width, 8)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_LSX; + } + } +#endif +#if defined(HAS_ARGBTOYMATRIXROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LASX; + if (IS_ALIGNED(width, 16)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_LASX; + } + } +#endif +#if defined(HAS_ARGBTOYMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_RVV; + } +#endif #if defined(HAS_ARGBTOYMATRIXROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { ARGBToYMatrixRow = ARGBToYMatrixRow_Any_WASMSIMD; @@ -2168,6 +2259,11 @@ int ARGBToUYVYMatrix(const uint8_t* src_argb, } } #endif +#if defined(HAS_ARGBTOUVMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + ARGBToUVMatrixRow = ARGBToUVMatrixRow_RVV; + } +#endif #if defined(HAS_ARGBTOUVMATRIXROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { ARGBToUVMatrixRow = ARGBToUVMatrixRow_Any_WASMSIMD; @@ -2205,6 +2301,22 @@ int ARGBToUYVYMatrix(const uint8_t* src_argb, } } #endif +#if defined(HAS_I422TOUYVYROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + I422ToUYVYRow = I422ToUYVYRow_Any_LSX; + if (IS_ALIGNED(width, 16)) { + I422ToUYVYRow = I422ToUYVYRow_LSX; + } + } +#endif +#if defined(HAS_I422TOUYVYROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + I422ToUYVYRow = I422ToUYVYRow_Any_LASX; + if (IS_ALIGNED(width, 32)) { + I422ToUYVYRow = I422ToUYVYRow_LASX; + } + } +#endif { align_buffer_64(row_y, ((width + 63) & ~63) * 2); @@ -4678,6 +4790,11 @@ static int RAWToNVMatrix(const uint8_t* src_raw, } } #endif +#if defined(HAS_RGBTOUVMATRIXROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + RGBToUVMatrixRow = RGBToUVMatrixRow_RVV; + } +#endif #if defined(HAS_RGBTOUVMATRIXROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { RGBToUVMatrixRow = RGBToUVMatrixRow_Any_WASMSIMD; diff --git a/source/convert_to_argb.cc b/source/convert_to_argb.cc index 17842d285..02caa89ea 100644 --- a/source/convert_to_argb.cc +++ b/source/convert_to_argb.cc @@ -461,35 +461,31 @@ int ConvertToARGB(const uint8_t* sample, // Biplanar formats case FOURCC_NV12: src = sample + ((ptrdiff_t)src_width * crop_y + crop_x); - src_uv = sample + - aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y / 2) + - (crop_x & ~1); + src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) + + ((ptrdiff_t)(crop_y / 2) * aligned_src_width) + (crop_x & ~1); r = NV12ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb, dst_stride_argb, crop_width, inv_crop_height); break; case FOURCC_NV21: src = sample + ((ptrdiff_t)src_width * crop_y + crop_x); - src_uv = sample + - aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y / 2) + - (crop_x & ~1); + src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) + + ((ptrdiff_t)(crop_y / 2) * aligned_src_width) + (crop_x & ~1); // Call NV12 but with u and v parameters swapped. r = NV21ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb, dst_stride_argb, crop_width, inv_crop_height); break; case FOURCC_NV16: src = sample + ((ptrdiff_t)src_width * crop_y + crop_x); - src_uv = sample + - aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y) + - (crop_x & ~1); + src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) + + ((ptrdiff_t)crop_y * aligned_src_width) + (crop_x & ~1); r = NV16ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb, dst_stride_argb, crop_width, inv_crop_height); break; case FOURCC_NV24: src = sample + ((ptrdiff_t)src_width * crop_y + crop_x); - src_uv = sample + (ptrdiff_t)aligned_src_width * abs_src_height + - (ptrdiff_t)aligned_src_width * 2 * crop_y + - (ptrdiff_t)crop_x * 2; - r = NV24ToARGB(src, src_width, src_uv, aligned_src_width * 2, dst_argb, + src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) + + ((ptrdiff_t)crop_y * src_width * 2) + ((ptrdiff_t)crop_x * 2); + r = NV24ToARGB(src, src_width, src_uv, src_width * 2, dst_argb, dst_stride_argb, crop_width, inv_crop_height); break; case FOURCC_P010: { diff --git a/source/convert_to_i420.cc b/source/convert_to_i420.cc index e5a094df9..f1967f813 100644 --- a/source/convert_to_i420.cc +++ b/source/convert_to_i420.cc @@ -19,6 +19,7 @@ #include "libyuv/cpu_id.h" #include "libyuv/planar_functions.h" #include "libyuv/row.h" +#include "libyuv/scale_row.h" #include "libyuv/video_common.h" #ifdef __cplusplus @@ -213,11 +214,17 @@ static int NV24ToI420(const uint8_t* src_y, int dst_stride_v, int width, int height) { - int x, y; + int y; int halfwidth = (width + 1) >> 1; int halfheight = (height + 1) >> 1; - void (*HalfRow)(const uint8_t* src_uv, ptrdiff_t src_uv_stride, - uint8_t* dst_uv, int width) = HalfRow_C; + void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr, + ptrdiff_t src_stride, int dst_width, + int source_y_fraction) = InterpolateRow_C; + void (*ScaleUVRowDown2Linear)(const uint8_t* src_uv, ptrdiff_t src_stride, + uint8_t* dst_uv, int dst_width) = + ScaleUVRowDown2Linear_C; + void (*SplitUVRow)(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, + int width) = SplitUVRow_C; if ((!src_y && dst_y) || !src_uv || !dst_u || !dst_v || width <= 0 || height == 0 || height == INT_MIN) { return -1; @@ -235,40 +242,180 @@ static int NV24ToI420(const uint8_t* src_y, if (dst_y) { CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); } -#if defined(HAS_HALFROW_AVX2) +#if defined(HAS_INTERPOLATEROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { - HalfRow = HalfRow_Any_AVX2; + InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(width * 2, 32)) { - HalfRow = HalfRow_AVX2; + InterpolateRow = InterpolateRow_AVX2; } } #endif +#if defined(HAS_INTERPOLATEROW_AVX512BW) + if (TestCpuFlag(kCpuHasAVX512BW)) { + InterpolateRow = InterpolateRow_AVX512BW; + } +#endif +#if defined(HAS_INTERPOLATEROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + InterpolateRow = InterpolateRow_Any_NEON; + if (IS_ALIGNED(width * 2, 16)) { + InterpolateRow = InterpolateRow_NEON; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_SVE2) + if (TestCpuFlag(kCpuHasSVE2)) { + InterpolateRow = InterpolateRow_SVE2; + } +#endif +#if defined(HAS_INTERPOLATEROW_SME) + if (TestCpuFlag(kCpuHasSME)) { + InterpolateRow = InterpolateRow_SME; + } +#endif +#if defined(HAS_INTERPOLATEROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + InterpolateRow = InterpolateRow_Any_LSX; + if (IS_ALIGNED(width * 2, 16)) { + InterpolateRow = InterpolateRow_LSX; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + InterpolateRow = InterpolateRow_Any_LASX; + if (IS_ALIGNED(width * 2, 32)) { + InterpolateRow = InterpolateRow_LASX; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + InterpolateRow = InterpolateRow_RVV; + } +#endif +#if defined(HAS_INTERPOLATEROW_WASMSIMD) + if (TestCpuFlag(kCpuHasWASMSIMD)) { + InterpolateRow = InterpolateRow_Any_WASMSIMD; + if (IS_ALIGNED(width * 2, 16)) { + InterpolateRow = InterpolateRow_WASMSIMD; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_HVX) + if (TestCpuFlag(kCpuHasHVX)) { + InterpolateRow = InterpolateRow_HVX; + } +#endif +#if defined(HAS_SCALEUVROWDOWN2_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_Any_AVX2; + if (IS_ALIGNED(halfwidth, 8)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_AVX2; + } + } +#endif +#if defined(HAS_SCALEUVROWDOWN2_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_Any_NEON; + if (IS_ALIGNED(halfwidth, 8)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_NEON; + } + } +#endif +#if defined(HAS_SCALEUVROWDOWN2_SME) + if (TestCpuFlag(kCpuHasSME)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_SME; + } +#endif +#if defined(HAS_SCALEUVROWDOWN2_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_RVV; + } +#endif +#if defined(HAS_SCALEUVROWDOWN2_HVX) + if (TestCpuFlag(kCpuHasHVX)) { + ScaleUVRowDown2Linear = ScaleUVRowDown2Linear_HVX; + } +#endif +#if defined(HAS_SPLITUVROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + SplitUVRow = SplitUVRow_Any_SSE2; + if (IS_ALIGNED(halfwidth, 16)) { + SplitUVRow = SplitUVRow_SSE2; + } + } +#endif +#if defined(HAS_SPLITUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + SplitUVRow = SplitUVRow_Any_AVX2; + if (IS_ALIGNED(halfwidth, 32)) { + SplitUVRow = SplitUVRow_AVX2; + } + } +#endif +#if defined(HAS_SPLITUVROW_AVX512BW) + if (TestCpuFlag(kCpuHasAVX512BW)) { + SplitUVRow = SplitUVRow_AVX512BW; + } +#endif +#if defined(HAS_SPLITUVROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + SplitUVRow = SplitUVRow_Any_NEON; + if (IS_ALIGNED(halfwidth, 16)) { + SplitUVRow = SplitUVRow_NEON; + } + } +#endif +#if defined(HAS_SPLITUVROW_SVE2) + if (TestCpuFlag(kCpuHasSVE2)) { + SplitUVRow = SplitUVRow_SVE2; + } +#endif +#if defined(HAS_SPLITUVROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + SplitUVRow = SplitUVRow_Any_LSX; + if (IS_ALIGNED(halfwidth, 16)) { + SplitUVRow = SplitUVRow_LSX; + } + } +#endif +#if defined(HAS_SPLITUVROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + SplitUVRow = SplitUVRow_Any_LASX; + if (IS_ALIGNED(halfwidth, 32)) { + SplitUVRow = SplitUVRow_LASX; + } + } +#endif +#if defined(HAS_SPLITUVROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + SplitUVRow = SplitUVRow_RVV; + } +#endif +#if defined(HAS_SPLITUVROW_HVX) + if (TestCpuFlag(kCpuHasHVX)) { + SplitUVRow = SplitUVRow_HVX; + } +#endif - align_buffer_64(row_uv, width * 2); + align_buffer_64(row_uv, halfwidth * 6); if (!row_uv) { return 1; } + uint8_t* row_uv_down = row_uv + halfwidth * 4; for (y = 0; y < halfheight; ++y) { if (y * 2 + 1 < height) { - HalfRow(src_uv, src_stride_uv, row_uv, width * 2); + InterpolateRow(row_uv, src_uv, src_stride_uv, width * 2, 128); } else { memcpy(row_uv, src_uv, (size_t)width * 2); } - for (x = 0; x < halfwidth - 1; ++x) { - dst_u[x] = (row_uv[x * 4 + 0] + row_uv[x * 4 + 2] + 1) >> 1; - dst_v[x] = (row_uv[x * 4 + 1] + row_uv[x * 4 + 3] + 1) >> 1; - } if (width & 1) { - dst_u[halfwidth - 1] = row_uv[(halfwidth - 1) * 4 + 0]; - dst_v[halfwidth - 1] = row_uv[(halfwidth - 1) * 4 + 1]; - } else { - dst_u[halfwidth - 1] = (row_uv[(halfwidth - 1) * 4 + 0] + - row_uv[(halfwidth - 1) * 4 + 2] + 1) >> - 1; - dst_v[halfwidth - 1] = (row_uv[(halfwidth - 1) * 4 + 1] + - row_uv[(halfwidth - 1) * 4 + 3] + 1) >> - 1; + row_uv[width * 2 + 0] = row_uv[width * 2 - 2]; + row_uv[width * 2 + 1] = row_uv[width * 2 - 1]; } + ScaleUVRowDown2Linear(row_uv, 0, row_uv_down, halfwidth); + SplitUVRow(row_uv_down, dst_u, dst_v, halfwidth); src_uv += (ptrdiff_t)src_stride_uv * 2; dst_u += dst_stride_u; dst_v += dst_stride_v; @@ -471,7 +618,7 @@ int ConvertToI420(const uint8_t* sample, break; case FOURCC_NV16: src = sample + ((ptrdiff_t)src_width * crop_y + crop_x); - src_uv = sample + ((ptrdiff_t)aligned_src_width * abs_src_height) + + src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) + ((ptrdiff_t)crop_y * aligned_src_width) + ((crop_x / 2) * 2); r = NV16ToI420(src, src_width, src_uv, aligned_src_width, dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, @@ -479,11 +626,11 @@ int ConvertToI420(const uint8_t* sample, break; case FOURCC_NV24: src = sample + ((ptrdiff_t)src_width * crop_y + crop_x); - src_uv = sample + ((ptrdiff_t)aligned_src_width * abs_src_height) + - ((ptrdiff_t)crop_y * aligned_src_width * 2) + (crop_x * 2); - r = NV24ToI420(src, src_width, src_uv, aligned_src_width * 2, dst_y, - dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, - crop_width, inv_crop_height); + src_uv = sample + ((ptrdiff_t)src_width * abs_src_height) + + ((ptrdiff_t)crop_y * src_width * 2) + (crop_x * 2); + r = NV24ToI420(src, src_width, src_uv, src_width * 2, dst_y, dst_stride_y, + dst_u, dst_stride_u, dst_v, dst_stride_v, crop_width, + inv_crop_height); break; case FOURCC_P010: { const uint16_t* src16 = (const uint16_t*)sample; diff --git a/source/planar_functions.cc b/source/planar_functions.cc index c30764490..3df4cc060 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -1289,7 +1289,8 @@ int NV12ToNV21(const uint8_t* src_y, int halfwidth = (width + 1) >> 1; int halfheight = (height + 1) >> 1; - if (!src_uv || !dst_vu || width <= 0 || height == 0 || height == INT_MIN) { + if ((!src_y && dst_y) || !src_uv || !dst_vu || width <= 0 || height == 0 || + height == INT_MIN) { return -1; } @@ -1331,7 +1332,7 @@ int DetilePlane(const uint8_t* src_y, void (*DetileRow)(const uint8_t* src, ptrdiff_t src_tile_stride, uint8_t* dst, int width) = DetileRow_C; if (!src_y || !dst_y || width <= 0 || height == 0 || height == INT_MIN || - !IS_POWEROFTWO(tile_height)) { + tile_height <= 0 || !IS_POWEROFTWO(tile_height)) { return -1; } @@ -1388,7 +1389,7 @@ int DetilePlane_16(const uint16_t* src_y, void (*DetileRow_16)(const uint16_t* src, ptrdiff_t src_tile_stride, uint16_t* dst, int width) = DetileRow_16_C; if (!src_y || !dst_y || width <= 0 || height == 0 || height == INT_MIN || - !IS_POWEROFTWO(tile_height)) { + tile_height <= 0 || !IS_POWEROFTWO(tile_height)) { return -1; } @@ -1450,8 +1451,8 @@ void DetileSplitUVPlane(const uint8_t* src_uv, // tile_height must be a power of 2 (16 or 32); the row loop below uses it as // a bit mask. - if (width <= 0 || height == 0 || height == INT_MIN || tile_height <= 0 || - !IS_POWEROFTWO(tile_height)) { + if (!src_uv || !dst_u || !dst_v || width <= 0 || height == 0 || + height == INT_MIN || tile_height <= 0 || !IS_POWEROFTWO(tile_height)) { return; } // Negative height means invert the image. @@ -1517,8 +1518,8 @@ void DetileToYUY2(const uint8_t* src_y, // tile_height must be a power of 2 and at least 2 (16 or 32); the row loop // uses it as a bit mask and the UV tile is tile_height / 2 rows. - if (width <= 0 || height == 0 || height == INT_MIN || tile_height < 2 || - !IS_POWEROFTWO(tile_height)) { + if (!src_y || !src_uv || !dst_yuy2 || width <= 0 || height == 0 || + height == INT_MIN || tile_height < 2 || !IS_POWEROFTWO(tile_height)) { return; } // Negative height means invert the image. @@ -2162,7 +2163,7 @@ void MergeXR30Plane(const uint16_t* src_r, } } else { MergeXR30Row = MergeXR30Row_Any_NEON; - if (IS_ALIGNED(width, 8)) { + if (IS_ALIGNED(width, 4)) { MergeXR30Row = MergeXR30Row_NEON; } } @@ -2765,6 +2766,22 @@ int YUY2ToY(const uint8_t* src_yuy2, YUY2ToYRow = YUY2ToYRow_SVE2; } #endif +#if defined(HAS_YUY2TOYROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + YUY2ToYRow = YUY2ToYRow_Any_LSX; + if (IS_ALIGNED(width, 16)) { + YUY2ToYRow = YUY2ToYRow_LSX; + } + } +#endif +#if defined(HAS_YUY2TOYROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + YUY2ToYRow = YUY2ToYRow_Any_LASX; + if (IS_ALIGNED(width, 32)) { + YUY2ToYRow = YUY2ToYRow_LASX; + } + } +#endif #if defined(HAS_YUY2TOYROW_HVX) if (TestCpuFlag(kCpuHasHVX)) { YUY2ToYRow = YUY2ToYRow_HVX; @@ -3693,7 +3710,7 @@ int BlendPlane(const uint8_t* src_y0, #if defined(HAS_BLENDPLANEROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { BlendPlaneRow = BlendPlaneRow_Any_WASMSIMD; - if (IS_ALIGNED(width, 8)) { + if (IS_ALIGNED(width, 16)) { BlendPlaneRow = BlendPlaneRow_WASMSIMD; } } @@ -3757,8 +3774,13 @@ int I420Blend(const uint8_t* src_y0, // Negative height means invert the image. if (height < 0) { height = -height; + int halfheight = (height + 1) >> 1; dst_y = dst_y + (ptrdiff_t)(height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; + dst_u = dst_u + (ptrdiff_t)(halfheight - 1) * dst_stride_u; + dst_stride_u = -dst_stride_u; + dst_v = dst_v + (ptrdiff_t)(halfheight - 1) * dst_stride_v; + dst_stride_v = -dst_stride_v; } // Blend Y plane. @@ -3802,7 +3824,7 @@ int I420Blend(const uint8_t* src_y0, #if defined(HAS_BLENDPLANEROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { BlendPlaneRow = BlendPlaneRow_Any_WASMSIMD; - if (IS_ALIGNED(halfwidth, 8)) { + if (IS_ALIGNED(halfwidth, 16)) { BlendPlaneRow = BlendPlaneRow_WASMSIMD; } } @@ -3856,9 +3878,10 @@ int I420Blend(const uint8_t* src_y0, } } #endif -#if defined(HAS_SCALEROWDOWN2_RVV) +#if defined(HAS_SCALEROWDOWN2BOX_RVV) if (TestCpuFlag(kCpuHasRVV)) { - ScaleRowDown2 = ScaleRowDown2Box_RVV; + ScaleRowDown2 = + IS_ALIGNED(width, 2) ? ScaleRowDown2Box_RVV : ScaleRowDown2Box_Odd_RVV; } #endif #if defined(HAS_SCALEROWDOWN2_WASMSIMD) @@ -4486,18 +4509,18 @@ int I420Rect(uint8_t* dst_y, int value_y, int value_u, int value_v) { - int halfwidth = (width + 1) >> 1; - int halfheight = (height + 1) >> 1; - uint8_t* start_y = dst_y + y * dst_stride_y + x; - uint8_t* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2); - uint8_t* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2); - if (!dst_y || !dst_u || !dst_v || width <= 0 || height == 0 || height == INT_MIN || x < 0 || y < 0 || value_y < 0 || value_y > 255 || value_u < 0 || value_u > 255 || value_v < 0 || value_v > 255) { return -1; } + int halfwidth = (width + 1) >> 1; + int halfheight = (height < 0) ? -((-height + 1) >> 1) : ((height + 1) >> 1); + uint8_t* start_y = dst_y + (ptrdiff_t)y * dst_stride_y + x; + uint8_t* start_u = dst_u + (ptrdiff_t)(y / 2) * dst_stride_u + (x / 2); + uint8_t* start_v = dst_v + (ptrdiff_t)(y / 2) * dst_stride_v + (x / 2); + SetPlane(start_y, dst_stride_y, width, height, value_y); SetPlane(start_u, dst_stride_u, halfwidth, halfheight, value_u); SetPlane(start_v, dst_stride_v, halfwidth, halfheight, value_v); @@ -5629,15 +5652,15 @@ int I420Interpolate(const uint8_t* src0_y, int width, int height, int interpolation) { - int halfwidth = (width + 1) >> 1; - int halfheight = (height + 1) >> 1; - if (!src0_y || !src0_u || !src0_v || !src1_y || !src1_u || !src1_v || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 || height == INT_MIN) { return -1; } + int halfwidth = (width + 1) >> 1; + int halfheight = (height < 0) ? -((-height + 1) >> 1) : ((height + 1) >> 1); + InterpolatePlane(src0_y, src0_stride_y, src1_y, src1_stride_y, dst_y, dst_stride_y, width, height, interpolation); InterpolatePlane(src0_u, src0_stride_u, src1_u, src1_stride_u, dst_u, @@ -5802,6 +5825,22 @@ int AR64Shuffle(const uint16_t* src_ar64, } } #endif +#if defined(HAS_ARGBSHUFFLEROW_LSX) + if (TestCpuFlag(kCpuHasLSX)) { + AR64ShuffleRow = ARGBShuffleRow_Any_LSX; + if (IS_ALIGNED(width, 4)) { + AR64ShuffleRow = ARGBShuffleRow_LSX; + } + } +#endif +#if defined(HAS_ARGBSHUFFLEROW_LASX) + if (TestCpuFlag(kCpuHasLASX)) { + AR64ShuffleRow = ARGBShuffleRow_Any_LASX; + if (IS_ALIGNED(width, 8)) { + AR64ShuffleRow = ARGBShuffleRow_LASX; + } + } +#endif #if defined(HAS_ARGBSHUFFLEROW_WASMSIMD) if (TestCpuFlag(kCpuHasWASMSIMD)) { AR64ShuffleRow = ARGBShuffleRow_Any_WASMSIMD; @@ -5994,6 +6033,11 @@ static int ARGBSobelize(const uint8_t* src_argb, ARGBToYMatrixRow = ARGBToYMatrixRow_SVE2; } #endif +#if defined(HAS_ARGBTOYMATRIXROW_SME) + if (TestCpuFlag(kCpuHasSME)) { + ARGBToYMatrixRow = ARGBToYMatrixRow_SME; + } +#endif #if defined(HAS_ARGBTOYMATRIXROW_LSX) if (TestCpuFlag(kCpuHasLSX)) { ARGBToYMatrixRow = ARGBToYMatrixRow_Any_LSX; @@ -6769,7 +6813,7 @@ int YUY2ToNV12(const uint8_t* src_yuy2, YUY2ToYRow = YUY2ToYRow_SVE2; } #endif -#if defined(HAS_YUY2TOYROW_LSX) && defined(HAS_YUY2TOUV422ROW_LSX) +#if defined(HAS_YUY2TOYROW_LSX) if (TestCpuFlag(kCpuHasLSX)) { YUY2ToYRow = YUY2ToYRow_Any_LSX; if (IS_ALIGNED(width, 16)) { @@ -6777,7 +6821,7 @@ int YUY2ToNV12(const uint8_t* src_yuy2, } } #endif -#if defined(HAS_YUY2TOYROW_LASX) && defined(HAS_YUY2TOUV422ROW_LASX) +#if defined(HAS_YUY2TOYROW_LASX) if (TestCpuFlag(kCpuHasLASX)) { YUY2ToYRow = YUY2ToYRow_Any_LASX; if (IS_ALIGNED(width, 32)) { @@ -7043,8 +7087,11 @@ void HalfMergeUVPlane(const uint8_t* src_u, src_stride_v = -src_stride_v; } #if defined(HAS_HALFMERGEUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { - HalfMergeUVRow = HalfMergeUVRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + HalfMergeUVRow = HalfMergeUVRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + HalfMergeUVRow = HalfMergeUVRow_NEON; + } } #endif #if defined(HAS_HALFMERGEUVROW_SVE2) diff --git a/source/rotate.cc b/source/rotate.cc index db72843a2..30dc57a37 100644 --- a/source/rotate.cc +++ b/source/rotate.cc @@ -555,8 +555,11 @@ void SplitRotateUV180(const uint8_t* src, void (*MirrorSplitUVRow)(const uint8_t* src, uint8_t* dst_u, uint8_t* dst_v, int width) = MirrorSplitUVRow_C; #if defined(HAS_MIRRORSPLITUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { - MirrorSplitUVRow = MirrorSplitUVRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + MirrorSplitUVRow = MirrorSplitUVRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + MirrorSplitUVRow = MirrorSplitUVRow_NEON; + } } #endif #if defined(HAS_MIRRORSPLITUVROW_SSSE3) @@ -581,18 +584,27 @@ void SplitRotateUV180(const uint8_t* src, } #endif #if defined(HAS_MIRRORSPLITUVROW_LSX) - if (TestCpuFlag(kCpuHasLSX) && IS_ALIGNED(width, 16)) { - MirrorSplitUVRow = MirrorSplitUVRow_LSX; + if (TestCpuFlag(kCpuHasLSX)) { + MirrorSplitUVRow = MirrorSplitUVRow_Any_LSX; + if (IS_ALIGNED(width, 16)) { + MirrorSplitUVRow = MirrorSplitUVRow_LSX; + } } #endif #if defined(HAS_MIRRORSPLITUVROW_LASX) - if (TestCpuFlag(kCpuHasLASX) && IS_ALIGNED(width, 32)) { - MirrorSplitUVRow = MirrorSplitUVRow_LASX; + if (TestCpuFlag(kCpuHasLASX)) { + MirrorSplitUVRow = MirrorSplitUVRow_Any_LASX; + if (IS_ALIGNED(width, 32)) { + MirrorSplitUVRow = MirrorSplitUVRow_LASX; + } } #endif #if defined(HAS_MIRRORSPLITUVROW_WASMSIMD) - if (TestCpuFlag(kCpuHasWASMSIMD) && IS_ALIGNED(width, 16)) { - MirrorSplitUVRow = MirrorSplitUVRow_WASMSIMD; + if (TestCpuFlag(kCpuHasWASMSIMD)) { + MirrorSplitUVRow = MirrorSplitUVRow_Any_WASMSIMD; + if (IS_ALIGNED(width, 16)) { + MirrorSplitUVRow = MirrorSplitUVRow_WASMSIMD; + } } #endif #if defined(HAS_MIRRORSPLITUVROW_HVX) diff --git a/source/rotate_argb.cc b/source/rotate_argb.cc index 1b0bf7417..2fb5962bb 100644 --- a/source/rotate_argb.cc +++ b/source/rotate_argb.cc @@ -173,6 +173,13 @@ static int ARGBTranspose(const uint8_t* src_argb, } } if (width > 0) { +#if defined(HAS_TRANSPOSEWXH_32_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + TransposeWxH_32_NEON(src_argb, src_stride_argb, dst_argb, + dst_stride_argb, width, height); + return 0; + } +#endif TransposeWxH_32_C(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width, height); } diff --git a/source/row_any.cc b/source/row_any.cc index 9c6d3ccb3..9036e0b13 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -878,6 +878,9 @@ ANY21HMS(HalfMergeUVRow_Any_SSSE3, HalfMergeUVRow_SSSE3, 15) #ifdef HAS_HALFMERGEUVROW_AVX2 ANY21HMS(HalfMergeUVRow_Any_AVX2, HalfMergeUVRow_AVX2, 31) #endif +#ifdef HAS_HALFMERGEUVROW_NEON +ANY21HMS(HalfMergeUVRow_Any_NEON, HalfMergeUVRow_NEON, 15) +#endif #undef ANY21HMS // Any 2 planes to 1 with yuvconstants @@ -1244,7 +1247,7 @@ ANY11(RAWToRGB24Row_Any_WASMSIMD, RAWToRGB24Row_WASMSIMD, 0, 3, 3, 15) #endif #ifdef HAS_UYVYTOYROW_AVX2 -ANY11(UYVYToYRow_Any_AVX2, UYVYToYRow_AVX2, 0, 2, 1, 31) +ANY11(UYVYToYRow_Any_AVX2, UYVYToYRow_AVX2, 1, 4, 1, 31) #endif #ifdef HAS_YUY2TOYROW_AVX2 ANY11(YUY2ToYRow_Any_AVX2, YUY2ToYRow_AVX2, 1, 4, 1, 31) @@ -2332,6 +2335,18 @@ ANY12MR(MirrorSplitUVRow_Any_SSSE3, MirrorSplitUVRow_SSSE3, 7) #ifdef HAS_MIRRORSPLITUVROW_AVX2 ANY12MR(MirrorSplitUVRow_Any_AVX2, MirrorSplitUVRow_AVX2, 15) #endif +#ifdef HAS_MIRRORSPLITUVROW_NEON +ANY12MR(MirrorSplitUVRow_Any_NEON, MirrorSplitUVRow_NEON, 15) +#endif +#ifdef HAS_MIRRORSPLITUVROW_LSX +ANY12MR(MirrorSplitUVRow_Any_LSX, MirrorSplitUVRow_LSX, 15) +#endif +#ifdef HAS_MIRRORSPLITUVROW_LASX +ANY12MR(MirrorSplitUVRow_Any_LASX, MirrorSplitUVRow_LASX, 31) +#endif +#ifdef HAS_MIRRORSPLITUVROW_WASMSIMD +ANY12MR(MirrorSplitUVRow_Any_WASMSIMD, MirrorSplitUVRow_WASMSIMD, 15) +#endif #undef ANY12MR // Any 1 plane. (memset) @@ -2417,6 +2432,8 @@ ANY12(SplitUVRow_Any_LASX, SplitUVRow_LASX, 0, 2, 0, 31) #endif #ifdef HAS_YUY2TOUV422ROW_AVX2 ANY12(YUY2ToUV422Row_Any_AVX2, YUY2ToUV422Row_AVX2, 1, 4, 1, 31) +#endif +#ifdef HAS_UYVYTOUV422ROW_AVX2 ANY12(UYVYToUV422Row_Any_AVX2, UYVYToUV422Row_AVX2, 1, 4, 1, 31) #endif #ifdef HAS_YUY2TOUV422ROW_SSE2 @@ -2816,6 +2833,8 @@ ANY11MC(ARGB4444ToYMatrixRow_Any_WASMSIMD, ARGB4444ToYMatrixRow_WASMSIMD, 2, 15) #ifdef HAS_YUY2TOUVROW_AVX2 ANY12S(YUY2ToUVRow_Any_AVX2, YUY2ToUVRow_AVX2, 1, 4, 31) +#endif +#ifdef HAS_UYVYTOUVROW_AVX2 ANY12S(UYVYToUVRow_Any_AVX2, UYVYToUVRow_AVX2, 1, 4, 31) #endif #ifdef HAS_YUY2TOUVROW_SSE2 diff --git a/source/row_common.cc b/source/row_common.cc index 48eda2282..19ebaa8db 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -231,7 +231,8 @@ void AR30ToARGBRow_C(const uint8_t* src_ar30, uint8_t* dst_argb, int width) { uint32_t g = (ar30 >> 12) & 0xff; uint32_t r = (ar30 >> 22) & 0xff; uint32_t a = (ar30 >> 30) * 0x55; // Replicate 2 bits to 8 bits. - *(uint32_t*)(dst_argb) = b | (g << 8) | (r << 16) | (a << 24); + uint32_t argb = b | (g << 8) | (r << 16) | (a << 24); + memcpy(dst_argb, &argb, sizeof argb); dst_argb += 4; src_ar30 += 4; } @@ -246,7 +247,8 @@ void AR30ToABGRRow_C(const uint8_t* src_ar30, uint8_t* dst_abgr, int width) { uint32_t g = (ar30 >> 12) & 0xff; uint32_t r = (ar30 >> 22) & 0xff; uint32_t a = (ar30 >> 30) * 0x55; // Replicate 2 bits to 8 bits. - *(uint32_t*)(dst_abgr) = r | (g << 8) | (b << 16) | (a << 24); + uint32_t abgr = r | (g << 8) | (b << 16) | (a << 24); + memcpy(dst_abgr, &abgr, sizeof abgr); dst_abgr += 4; src_ar30 += 4; } @@ -260,7 +262,8 @@ void AR30ToAB30Row_C(const uint8_t* src_ar30, uint8_t* dst_ab30, int width) { uint32_t b = ar30 & 0x3ff; uint32_t ga = ar30 & 0xc00ffc00; uint32_t r = (ar30 >> 20) & 0x3ff; - *(uint32_t*)(dst_ab30) = r | ga | (b << 20); + uint32_t ab30 = r | ga | (b << 20); + memcpy(dst_ab30, &ab30, sizeof ab30); dst_ab30 += 4; src_ar30 += 4; } @@ -481,8 +484,9 @@ void ABGRToAR30Row_C(const uint8_t* src_abgr, uint8_t* dst_ar30, int width) { uint32_t g0 = (src_abgr[1] >> 6) | ((uint32_t)(src_abgr[1]) << 2); uint32_t b0 = (src_abgr[2] >> 6) | ((uint32_t)(src_abgr[2]) << 2); uint32_t a0 = (src_abgr[3] >> 6); - *(uint32_t*)(dst_ar30) = + uint32_t ar30 = STATIC_CAST(uint32_t, b0 | (g0 << 10) | (r0 << 20) | (a0 << 30)); + memcpy(dst_ar30, &ar30, sizeof ar30); dst_ar30 += 4; src_abgr += 4; } @@ -495,8 +499,9 @@ void ARGBToAR30Row_C(const uint8_t* src_argb, uint8_t* dst_ar30, int width) { uint32_t g0 = (src_argb[1] >> 6) | ((uint32_t)(src_argb[1]) << 2); uint32_t r0 = (src_argb[2] >> 6) | ((uint32_t)(src_argb[2]) << 2); uint32_t a0 = (src_argb[3] >> 6); - *(uint32_t*)(dst_ar30) = + uint32_t ar30 = STATIC_CAST(uint32_t, b0 | (g0 << 10) | (r0 << 20) | (a0 << 30)); + memcpy(dst_ar30, &ar30, sizeof ar30); dst_ar30 += 4; src_argb += 4; } @@ -2067,7 +2072,7 @@ static void StoreAR30(uint8_t* rgb_buf, int b, int g, int r) { g = Clamp10(g); r = Clamp10(r); ar30 = b | ((uint32_t)g << 10) | ((uint32_t)r << 20) | 0xc0000000; - (*(uint32_t*)rgb_buf) = ar30; + memcpy(rgb_buf, &ar30, sizeof ar30); } // 10 bit YUV to 10 bit AR30 @@ -2966,12 +2971,13 @@ void MergeXR30Row_C(const uint16_t* src_r, assert(depth <= 16); int x; int shift = depth - 10; - uint32_t* dst_ar30_32 = (uint32_t*)dst_ar30; for (x = 0; x < width; ++x) { uint32_t r = clamp1023(src_r[x] >> shift); uint32_t g = clamp1023(src_g[x] >> shift); uint32_t b = clamp1023(src_b[x] >> shift); - dst_ar30_32[x] = b | (g << 10) | (r << 20) | 0xc0000000; + uint32_t ar30 = b | (g << 10) | (r << 20) | 0xc0000000; + memcpy(dst_ar30, &ar30, sizeof ar30); + dst_ar30 += 4; } } @@ -3634,9 +3640,8 @@ void ARGBAffineRow_C(const uint8_t* src_argb, for (i = 0; i < width; ++i) { int x = (int)(uv[0]); int y = (int)(uv[1]); - *(uint32_t*)(dst_argb) = - *(const uint32_t*)(src_argb + (ptrdiff_t)y * src_argb_stride + - (ptrdiff_t)x * 4); + memcpy(dst_argb, + src_argb + (ptrdiff_t)y * src_argb_stride + (ptrdiff_t)x * 4, 4); dst_argb += 4; uv[0] += uv_dudv[2]; uv[1] += uv_dudv[3]; diff --git a/source/row_gcc.cc b/source/row_gcc.cc index 3abe073b0..5f13978ec 100644 --- a/source/row_gcc.cc +++ b/source/row_gcc.cc @@ -11107,7 +11107,9 @@ void YUY2ToYRow_AVX2(const uint8_t* src_yuy2, uint8_t* dst_y, int width) { : : "memory", "cc", "xmm0", "xmm1", "xmm5"); } +#endif // HAS_YUY2TOYROW_AVX2 +#ifdef HAS_YUY2TONVUVROW_AVX2 void YUY2ToNVUVRow_AVX2(const uint8_t* src_yuy2, int stride_yuy2, uint8_t* dst_uv, @@ -11134,7 +11136,9 @@ void YUY2ToNVUVRow_AVX2(const uint8_t* src_yuy2, : "r"((ptrdiff_t)(stride_yuy2)) // %3 : "memory", "cc", "xmm0", "xmm1"); } +#endif // HAS_YUY2TONVUVROW_AVX2 +#ifdef HAS_YUY2TOUVROW_AVX2 void YUY2ToUVRow_AVX2(const uint8_t* src_yuy2, int stride_yuy2, uint8_t* dst_u, @@ -11175,7 +11179,9 @@ void YUY2ToUVRow_AVX2(const uint8_t* src_yuy2, : "r"((ptrdiff_t)(stride_yuy2)) // %4 : "memory", "cc", "xmm0", "xmm1", "xmm5"); } +#endif // HAS_YUY2TOUVROW_AVX2 +#ifdef HAS_YUY2TOUV422ROW_AVX2 void YUY2ToUV422Row_AVX2(const uint8_t* src_yuy2, uint8_t* dst_u, uint8_t* dst_v, @@ -11213,7 +11219,9 @@ void YUY2ToUV422Row_AVX2(const uint8_t* src_yuy2, : : "memory", "cc", "xmm0", "xmm1", "xmm5"); } +#endif // HAS_YUY2TOUV422ROW_AVX2 +#ifdef HAS_UYVYTOYROW_AVX2 void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width) { asm volatile( "1: \n" @@ -11233,8 +11241,11 @@ void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width) { "+r"(dst_y), // %1 "+r"(width) // %2 : - : "memory", "cc", "xmm0", "xmm1", "xmm5"); + : "memory", "cc", "xmm0", "xmm1"); } +#endif // HAS_UYVYTOYROW_AVX2 + +#ifdef HAS_UYVYTOUVROW_AVX2 void UYVYToUVRow_AVX2(const uint8_t* src_uyvy, int stride_uyvy, uint8_t* dst_u, @@ -11275,7 +11286,9 @@ void UYVYToUVRow_AVX2(const uint8_t* src_uyvy, : "r"((ptrdiff_t)(stride_uyvy)) // %4 : "memory", "cc", "xmm0", "xmm1", "xmm5"); } +#endif // HAS_UYVYTOUVROW_AVX2 +#ifdef HAS_UYVYTOUV422ROW_AVX2 void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy, uint8_t* dst_u, uint8_t* dst_v, @@ -11313,7 +11326,7 @@ void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy, : : "memory", "cc", "xmm0", "xmm1", "xmm5"); } -#endif // HAS_YUY2TOYROW_AVX2 +#endif // HAS_UYVYTOUV422ROW_AVX2 #ifdef HAS_YUY2TOYROW_AVX512BW LIBYUV_TARGET_AVX512BW diff --git a/source/row_neon.cc b/source/row_neon.cc index ae4782d6b..4f0613ac5 100644 --- a/source/row_neon.cc +++ b/source/row_neon.cc @@ -2159,7 +2159,7 @@ void RGB24ToUVRow_NEON(const uint8_t* src_rgb24, "+r"(dst_v), // %3 "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + : "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -2204,7 +2204,7 @@ void RAWToUVRow_NEON(const uint8_t* src_raw, "+r"(dst_v), // %3 "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + : "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -2270,8 +2270,8 @@ void RGB565ToUVRow_NEON(const uint8_t* src_rgb565, "+r"(dst_v), // %3 "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", - "q9", "q10", "q11", "q12", "q13", "q14", "q15"); + : "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15"); } // 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. @@ -2335,8 +2335,8 @@ void ARGB1555ToUVRow_NEON(const uint8_t* src_argb1555, "+r"(dst_v), // %3 "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", - "q9", "q10", "q11", "q12", "q13", "q14", "q15"); + : "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15"); } // 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. @@ -2391,7 +2391,7 @@ void ARGB4444ToUVRow_NEON(const uint8_t* src_argb4444, "+r"(dst_v), // %3 "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", + : "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"); } diff --git a/source/row_neon64.cc b/source/row_neon64.cc index e39360537..14e6fd03d 100644 --- a/source/row_neon64.cc +++ b/source/row_neon64.cc @@ -1287,8 +1287,8 @@ void UnpackMT2T_NEON(const uint8_t* src, uint16_t* dst, size_t size) { "+r"(dst), // %1 "+r"(size) // %2 : - : "cc", "memory", "w0", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", - "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"); + : "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16", + "v17", "v18", "v19", "v20", "v21", "v22", "v23"); } #if defined(LIBYUV_USE_ST2) diff --git a/source/row_sme.cc b/source/row_sme.cc index 21abac922..f9b533ffb 100644 --- a/source/row_sme.cc +++ b/source/row_sme.cc @@ -500,7 +500,6 @@ __arm_locally_streaming void MergeUVRow_SME(const uint8_t* src_u, "whilelt p0.b, wzr, %w[width] \n" "ld1b {z1.b}, p0/z, [%[src_u]] \n" "ld1b {z2.b}, p0/z, [%[src_v]] \n" - "subs %w[width], %w[width], %w[vl] \n" "st2b {z1.b, z2.b}, p0, [%[dst_uv]] \n" "99: \n" @@ -510,7 +509,7 @@ __arm_locally_streaming void MergeUVRow_SME(const uint8_t* src_u, [width] "+r"(width), // %[width] [vl] "=&r"(vl) // %[vl] : - : "memory", "cc", "z0", "z1", "z2", "p0"); + : "memory", "cc", "z1", "z2", "p0"); } __arm_locally_streaming void MergeUVRow_16_SME(const uint16_t* src_u, @@ -552,7 +551,6 @@ __arm_locally_streaming void MergeUVRow_16_SME(const uint16_t* src_u, "ld1h {z2.h}, p0/z, [%[src_v]] \n" "lsl z1.h, p0/m, z1.h, z0.h \n" "lsl z2.h, p0/m, z2.h, z0.h \n" - "subs %w[width], %w[width], %w[vl] \n" "st2h {z1.h, z2.h}, p0, [%[dst_uv]] \n" "99: \n" @@ -624,7 +622,7 @@ __arm_locally_streaming void Convert16To8Row_SME(const uint16_t* src_y, [width] "+r"(width), // %[width] [vl] "=&r"(vl) // %[vl] : [shift] "r"(shift) // %[shift] - : "cc", "memory", "z0", "z1", "z2", "p0", "p1", "p2"); + : "memory", "cc", "z0", "z1", "z2", "p0", "p1", "p2"); } __arm_locally_streaming void CopyRow_SME(const uint8_t* src, @@ -701,7 +699,6 @@ __arm_locally_streaming static void HalfRow_SME(uint8_t* dst_ptr, "ld1b {z2.b}, p0/z, [%[src_ptr]] \n" "ld1b {z3.b}, p0/z, [%[src_ptr1]] \n" "urhadd z2.b, p0/m, z2.b, z3.b \n" - "subs %w[width], %w[width], %w[vl] \n" "st1b {z2.b}, p0, [%[dst_ptr]] \n" "99: \n" @@ -711,7 +708,7 @@ __arm_locally_streaming static void HalfRow_SME(uint8_t* dst_ptr, [width] "+r"(width), // %[width] [vl] "=&r"(vl) // %[vl] : - : "cc", "memory", "z0", "z1", "z2", "z3", "p0"); + : "memory", "cc", "z2", "z3", "p0"); } __arm_locally_streaming void InterpolateRow_SME(uint8_t* dst_ptr, @@ -787,7 +784,7 @@ __arm_locally_streaming void InterpolateRow_SME(uint8_t* dst_ptr, [vl] "=&r"(vl) // %[vl] : [y0_fraction] "r"(y0_fraction), // %[y0_fraction] [y1_fraction] "r"(y1_fraction) // %[y1_fraction] - : "cc", "memory", "z0", "z1", "z2", "z3", "z4", "p0"); + : "memory", "cc", "z0", "z1", "z2", "z3", "z4", "p0"); } __arm_locally_streaming static void HalfRow_16_SME(uint16_t* dst_ptr, @@ -834,7 +831,7 @@ __arm_locally_streaming static void HalfRow_16_SME(uint16_t* dst_ptr, [width] "+r"(width), // %[width] [vl] "=&r"(vl) // %[vl] : - : "cc", "memory", "z0", "z1", "z2", "z3", "p0"); + : "memory", "cc", "z2", "z3", "p0"); } __arm_locally_streaming void InterpolateRow_16_SME(uint16_t* dst_ptr, diff --git a/source/row_sve.cc b/source/row_sve.cc index cb5f73993..79771cbb2 100644 --- a/source/row_sve.cc +++ b/source/row_sve.cc @@ -480,7 +480,6 @@ void AYUVToVURow_SVE2(const uint8_t* src_ayuv, int vl; asm volatile ( "cntb %x[vl] \n" - "cmp %w[width], %w[vl] \n" "subs %w[width], %w[width], %w[vl] \n" "b.lt 2f \n" diff --git a/source/row_win.cc b/source/row_win.cc index ba6f7b56e..928942a1a 100644 --- a/source/row_win.cc +++ b/source/row_win.cc @@ -3570,6 +3570,7 @@ void ARGBBlendRow_AVX2(const uint8_t* src_argb0, #endif // HAS_ARGBBLENDROW_AVX2 #ifdef HAS_BLENDPLANEROW_SSSE3 +LIBYUV_TARGET_SSSE3 void BlendPlaneRow_SSSE3(const uint8_t* src0, const uint8_t* src1, const uint8_t* alpha, diff --git a/source/scale.cc b/source/scale.cc index f2157409c..29745956a 100644 --- a/source/scale.cc +++ b/source/scale.cc @@ -990,7 +990,7 @@ static int ScalePlaneBox(int src_width, } #endif #if defined(HAS_SCALEADDROW_WASMSIMD) - if (TestCpuFlag(kCpuHasWASM)) { + if (TestCpuFlag(kCpuHasWASMSIMD)) { ScaleAddRow = ScaleAddRow_Any_WASMSIMD; if (IS_ALIGNED(src_width, 16)) { ScaleAddRow = ScaleAddRow_WASMSIMD; diff --git a/source/scale_argb.cc b/source/scale_argb.cc index 53280ea16..70e2e69bf 100644 --- a/source/scale_argb.cc +++ b/source/scale_argb.cc @@ -450,7 +450,7 @@ static int ScaleARGBBilinearDown(int src_width, } #endif #if defined(HAS_SCALEARGBFILTERCOLS_NEON) - if (TestCpuFlag(kCpuHasNEON)) { + if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON; if (IS_ALIGNED(dst_width, 4)) { ScaleARGBFilterCols = ScaleARGBFilterCols_NEON; @@ -458,7 +458,7 @@ static int ScaleARGBBilinearDown(int src_width, } #endif #if defined(HAS_SCALEARGBFILTERCOLS_LSX) - if (TestCpuFlag(kCpuHasLSX)) { + if (TestCpuFlag(kCpuHasLSX) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_Any_LSX; if (IS_ALIGNED(dst_width, 4)) { ScaleARGBFilterCols = ScaleARGBFilterCols_LSX; @@ -466,7 +466,7 @@ static int ScaleARGBBilinearDown(int src_width, } #endif #if defined(HAS_SCALEARGBFILTERCOLS_RVV) - if (TestCpuFlag(kCpuHasRVV)) { + if (TestCpuFlag(kCpuHasRVV) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_RVV; } #endif @@ -613,7 +613,7 @@ static int ScaleARGBBilinearUp(int src_width, } #endif #if defined(HAS_SCALEARGBFILTERCOLS_NEON) - if (filtering && TestCpuFlag(kCpuHasNEON)) { + if (filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON; if (IS_ALIGNED(dst_width, 4)) { ScaleARGBFilterCols = ScaleARGBFilterCols_NEON; @@ -621,7 +621,7 @@ static int ScaleARGBBilinearUp(int src_width, } #endif #if defined(HAS_SCALEARGBFILTERCOLS_LSX) - if (filtering && TestCpuFlag(kCpuHasLSX)) { + if (filtering && TestCpuFlag(kCpuHasLSX) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_Any_LSX; if (IS_ALIGNED(dst_width, 4)) { ScaleARGBFilterCols = ScaleARGBFilterCols_LSX; @@ -629,7 +629,7 @@ static int ScaleARGBBilinearUp(int src_width, } #endif #if defined(HAS_SCALEARGBFILTERCOLS_RVV) - if (filtering && TestCpuFlag(kCpuHasRVV)) { + if (filtering && TestCpuFlag(kCpuHasRVV) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_RVV; } #endif @@ -639,7 +639,7 @@ static int ScaleARGBBilinearUp(int src_width, } #endif #if defined(HAS_SCALEARGBCOLS_NEON) - if (!filtering && TestCpuFlag(kCpuHasNEON)) { + if (!filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBCols_Any_NEON; if (IS_ALIGNED(dst_width, 8)) { ScaleARGBFilterCols = ScaleARGBCols_NEON; @@ -647,7 +647,7 @@ static int ScaleARGBBilinearUp(int src_width, } #endif #if defined(HAS_SCALEARGBCOLS_LSX) - if (!filtering && TestCpuFlag(kCpuHasLSX)) { + if (!filtering && TestCpuFlag(kCpuHasLSX) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBCols_Any_LSX; if (IS_ALIGNED(dst_width, 4)) { ScaleARGBFilterCols = ScaleARGBCols_LSX; @@ -778,7 +778,7 @@ static void ScaleARGBSimple(int src_width, } #endif #if defined(HAS_SCALEARGBCOLS_NEON) - if (TestCpuFlag(kCpuHasNEON)) { + if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) { ScaleARGBCols = ScaleARGBCols_Any_NEON; if (IS_ALIGNED(dst_width, 8)) { ScaleARGBCols = ScaleARGBCols_NEON; @@ -786,7 +786,7 @@ static void ScaleARGBSimple(int src_width, } #endif #if defined(HAS_SCALEARGBCOLS_LSX) - if (TestCpuFlag(kCpuHasLSX)) { + if (TestCpuFlag(kCpuHasLSX) && src_width < 32768) { ScaleARGBCols = ScaleARGBCols_Any_LSX; if (IS_ALIGNED(dst_width, 4)) { ScaleARGBCols = ScaleARGBCols_LSX; diff --git a/source/scale_rvv.cc b/source/scale_rvv.cc index 238a9a953..197ca85ff 100644 --- a/source/scale_rvv.cc +++ b/source/scale_rvv.cc @@ -393,6 +393,19 @@ void ScaleRowDown2Box_RVV(const uint8_t* src_ptr, : RVV_VL_CLOBBER "memory", "v8", "v9", "v10", "v11", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"); } + +void ScaleRowDown2Box_Odd_RVV(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width) { + dst_width -= 1; + if (dst_width > 0) { + ScaleRowDown2Box_RVV(src_ptr, src_stride, dst, dst_width); + } + const uint8_t* s = src_ptr + dst_width * 2; + const uint8_t* t = s + src_stride; + dst[dst_width] = (s[0] + t[0] + 1) >> 1; +} #endif #ifdef HAS_SCALEROWDOWN4_RVV diff --git a/source/scale_uv.cc b/source/scale_uv.cc index 706f27a80..6a3f2d181 100644 --- a/source/scale_uv.cc +++ b/source/scale_uv.cc @@ -454,7 +454,7 @@ static int ScaleUVBox(int src_width, } #endif #if defined(HAS_SCALEUVADDCOLS3_WASMSIMD) - if (TestCpuFlag(kCpuHasWASM)) { + if (TestCpuFlag(kCpuHasWASMSIMD)) { ScaleUVAddCols3 = ScaleUVAddCols3_Any_WASMSIMD; if (IS_ALIGNED(dst_width, 8)) { ScaleUVAddCols3 = ScaleUVAddCols3_WASMSIMD; @@ -515,7 +515,7 @@ static int ScaleUVBox(int src_width, } #endif #if defined(HAS_SCALEADDROW_WASMSIMD) - if (TestCpuFlag(kCpuHasWASM)) { + if (TestCpuFlag(kCpuHasWASMSIMD)) { ScaleAddRow = ScaleAddRow_Any_WASMSIMD; if (IS_ALIGNED(row_samples, 16)) { ScaleAddRow = ScaleAddRow_WASMSIMD; diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 5854b8903..6f0e42f2c 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -1582,8 +1582,7 @@ TEST_F(LibYUVPlanarTest, I420Blend_Unaligned) { disable_cpu_flags_, benchmark_cpu_info_, +1, 1); } -// TODO(fbarchard): DISABLED because _Any uses C. Avoid C and re-enable. -TEST_F(LibYUVPlanarTest, DISABLED_I420Blend_Any) { +TEST_F(LibYUVPlanarTest, I420Blend_Any) { TestI420Blend(benchmark_width_ + 1, benchmark_height_, benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_, +1, 0); }