[libyuv] Add NEON implementations for all remaining C row functions

Implement 32-bit and 64-bit Arm NEON versions (in row_neon.cc and
row_neon64.cc) for the 12 remaining row functions that previously fell
back to C on Arm:
- AR30ToAB30Row_NEON (and AR30ToAB30Row_Any_NEON)
- AR30ToABGRRow_NEON (and AR30ToABGRRow_Any_NEON)
- AR30ToARGBRow_NEON (and AR30ToARGBRow_Any_NEON)
- ARGBAffineRow_NEON
- ARGBColorTableRow_NEON
- ARGBCopyAlphaRow_NEON (and ARGBCopyAlphaRow_Any_NEON)
- ARGBLumaColorTableRow_NEON
- ARGBPolynomialRow_NEON (and ARGBPolynomialRow_Any_NEON)
- ARGBUnattenuateRow_NEON (and ARGBUnattenuateRow_Any_NEON)
- CopyRow_16_NEON (and CopyRow_16_Any_NEON)
- MirrorRow_16_NEON (and MirrorRow_16_Any_NEON)
- RGBColorTableRow_NEON

Add HAS_*_NEON macros, prototypes, _Any wrappers, NEON dispatches in
convert.cc, convert_argb.cc, and planar_functions.cc, and enable unit
tests in planar_test.cc. Arm row function SIMD coverage is now 164/164
(100%).

Maximum SIMD ISA supported per C row function:
------------------------------------------------------------------------
C Row Function        arm     x86        riscv wasm     loongson hexagon
------------------------------------------------------------------------
AB64ToARGBRow_C       NEON    AVX2       RVV   -        -        HVX
ABGRToAR30Row_C       NEON    AVX512BW   -     -        -        -
AR30ToAB30Row_C       NEON    AVX512BW   -     -        -        -
AR30ToABGRRow_C       NEON    AVX512BW   -     -        -        -
AR30ToARGBRow_C       NEON    AVX512BW   -     -        -        -
AR64ShuffleRow_C      NEON    AVX512BW   RVV   WASMSIMD -        -
AR64ToAB64Row_C       NEON    AVX512BW   RVV   WASMSIMD -        HVX
AR64ToARGBRow_C       NEON    AVX2       RVV   -        -        HVX
ARGB1555ToARGBRow_C   SVE2    AVX2       -     WASMSIMD LASX     -
ARGB1555ToUVMatrixRow_C NEON  AVX2       -     WASMSIMD -        -
ARGB1555ToUVRow_C     NEON    -          -     -        LASX     -
ARGB1555ToYMatrixRow_C NEON   AVX2       -     WASMSIMD -        -
ARGB1555ToYRow_C      NEON    -          -     -        LASX     -
ARGB4444ToARGBRow_C   NEON    AVX2       -     WASMSIMD LASX     -
ARGB4444ToUVMatrixRow_C NEON  AVX2       -     WASMSIMD -        -
ARGB4444ToUVRow_C     NEON    -          -     -        -        -
ARGB4444ToYMatrixRow_C NEON   AVX2       -     WASMSIMD -        -
ARGB4444ToYRow_C      NEON    -          -     -        -        -
ARGBAddRow_C          NEON    AVX2       -     -        LASX     HVX
ARGBAffineRow_C       NEON    SSE2       -     -        -        -
ARGBAlphaBlendRow_C   SME     AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBAttenuateRow_C    NEON    AVX512BW   RVV   -        LASX     HVX
ARGBBlendRow_C        NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBColorMatrixRow_C  I8MM    SSSE3      -     -        LASX     -
ARGBColorTableRow_C   NEON    X86        -     -        -        -
ARGBCopyAlphaRow_C    NEON    AVX2       -     -        -        HVX
ARGBCopyYToAlphaRow_C NEON    AVX512BW   RVV   WASMSIMD -        HVX
ARGBExtractAlphaRow_C NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBGrayRow_C         DOTPROD AVX512VNNI -     -        LASX     -
ARGBLumaColorTableRow_C NEON  SSSE3      -     -        -        -
ARGBMirrorRow_C       NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBMultiplyRow_C     SME     AVX512BW   RVV   -        LASX     HVX
ARGBOrRow_C           SME     AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBPolynomialRow_C   NEON    AVX2       -     -        -        -
ARGBQuantizeRow_C     NEON    SSE2       -     -        LASX     -
ARGBSepiaRow_C        DOTPROD SSSE3      -     -        LASX     -
ARGBSetRow_C          NEON    X86        RVV   -        LASX     HVX
ARGBShadeRow_C        NEON    SSE2       -     -        LASX     -
ARGBShuffleRow_C      NEON    AVX512BW   RVV   WASMSIMD LASX     -
ARGBSubtractRow_C     NEON    AVX2       -     -        LASX     HVX
ARGBToAB64Row_C       NEON    AVX2       RVV   -        -        HVX
ARGBToABGRRow_C       NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBToAR30Row_C       NEON    AVX512BW   -     -        -        -
ARGBToAR64Row_C       NEON    AVX2       RVV   -        -        HVX
ARGBToARGB1555Row_C   NEON    AVX2       -     WASMSIMD LASX     -
ARGBToARGB4444Row_C   NEON    AVX2       -     WASMSIMD LASX     -
ARGBToBGRARow_C       NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBToRAWRow_C        SVE2    AVX512BW   RVV   -        LASX     -
ARGBToRGB24Row_C      SVE2    AVX512BW   RVV   -        LASX     -
ARGBToRGB565DitherRow_C SVE2  AVX2       -     WASMSIMD LASX     -
ARGBToRGB565Row_C     SVE2    AVX2       -     WASMSIMD LASX     -
ARGBToRGBARow_C       NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
ARGBToUV444MatrixRow_C I8MM   AVX512VNNI RVV   WASMSIMD -        HVX
ARGBToUVMatrixRow_C   SME     AVX512VNNI RVV   WASMSIMD -        HVX
ARGBToYMatrixRow_C    SME     AVX512VNNI RVV   WASMSIMD LASX     HVX
ARGBUnattenuateRow_C  NEON    AVX2       -     -        -        -
AYUVToUVRow_C         SVE2    AVX512VBMI -     -        -        -
AYUVToVURow_C         SVE2    AVX512VBMI -     -        -        -
AYUVToYRow_C          NEON    AVX512VBMI -     -        -        -
BlendPlaneRow_C       NEON    AVX512BW   RVV   WASMSIMD -        HVX
ByteToFloatRow_C      NEON    -          -     -        -        -
ComputeCumulativeSumRow_C NEON AVX2      -     -        -        -
Convert16To8Row_C     SME     AVX512BW   RVV   -        -        HVX
Convert8To16Row_C     SME     AVX512BW   RVV   WASMSIMD -        HVX
Convert8To8Row_C      SME     AVX2       -     -        -        HVX
CopyRow_C             SME     AVX512BW   RVV   -        LASX     HVX
CopyRow_16_C          NEON    -          -     -        -        HVX
CumulativeSumToAverageRow_C NEON AVX2    -     -        -        -
DetileRow_C           NEON    SSE2       -     -        -        -
DetileRow_16_C        NEON    AVX        -     -        -        -
DetileSplitUVRow_C    NEON    SSSE3      -     -        -        -
DivideRow_16_C        SVE2    AVX2       -     -        -        HVX
GaussRow_C            NEON    -          -     -        -        -
GaussRow_F32_C        NEON    -          -     -        -        -
HalfFloatRow_C        SVE2    AVX2       -     -        LASX     -
HalfMergeUVRow_C      SVE2    AVX512BW   -     -        -        -
HalfRow_16To8_C       SME     AVX512BW   RVV   -        -        HVX
HalfWidthRow_16To8_C  SME     AVX512BW   RVV   -        -        -
I210AlphaToARGBRow_C  SME     AVX2       -     -        -        -
I210ToAR30Row_C       SME     AVX2       -     -        -        -
I210ToARGBRow_C       SME     AVX2       -     -        -        -
I212ToAR30Row_C       SME     AVX2       -     -        -        -
I212ToARGBRow_C       SME     AVX2       -     -        -        -
I400ToARGBRow_C       SME     AVX512BW   RVV   -        LASX     HVX
I410AlphaToARGBRow_C  SME     AVX2       -     -        -        -
I410ToAR30Row_C       SME     AVX2       -     -        -        -
I410ToARGBRow_C       SME     AVX2       -     -        -        -
I422AlphaToARGBRow_C  SME     AVX512BW   RVV   -        LASX     HVX
I422ToAR30Row_C       SME     AVX512BW   RVV   WASMSIMD -        -
I422ToARGB1555Row_C   SME     AVX2       -     WASMSIMD LASX     -
I422ToARGB4444Row_C   SME     AVX2       -     WASMSIMD LASX     -
I422ToARGBRow_C       SME     AVX512BW   RVV   WASMSIMD LASX     HVX
I422ToRGB24Row_C      SME     AVX512VBMI RVV   WASMSIMD LASX     -
I422ToRGB565Row_C     SME     AVX2       -     WASMSIMD LASX     -
I422ToRGBARow_C       SME     AVX2       RVV   -        LASX     HVX
I422ToUYVYRow_C       NEON    AVX2       -     -        LASX     -
I422ToYUY2Row_C       NEON    AVX2       -     -        LASX     -
I444AlphaToARGBRow_C  SME     AVX2       RVV   -        -        HVX
I444ToARGBRow_C       SME     AVX2       RVV   -        LASX     HVX
I444ToRGB24Row_C      SME     AVX2       RVV   -        -        -
InterpolateRow_C      SME     AVX512BW   RVV   WASMSIMD LASX     HVX
InterpolateRow_16_C   SME     AVX512BW   -     WASMSIMD -        HVX
J400ToARGBRow_C       NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
MergeAR64Row_C        NEON    AVX2       -     -        -        -
MergeARGB16To8Row_C   NEON    AVX2       -     -        -        -
MergeARGBRow_C        NEON    AVX2       RVV   -        -        HVX
MergeRGBRow_C         NEON    AVX512VBMI RVV   -        -        -
MergeUVRow_C          SME     AVX512BW   RVV   WASMSIMD LASX     HVX
MergeUVRow_16_C       SME     AVX2       -     -        -        HVX
MergeXR30Row_C        NEON    AVX512BW   -     -        -        -
MergeXR64Row_C        NEON    AVX2       -     -        -        -
MergeXRGB16To8Row_C   NEON    AVX2       -     -        -        -
MergeXRGBRow_C        NEON    AVX2       RVV   -        -        HVX
MirrorRow_C           NEON    AVX512BW   -     WASMSIMD LASX     HVX
MirrorRow_16_C        NEON    AVX512BW   -     -        -        HVX
MirrorSplitUVRow_C    NEON    AVX512BW   -     WASMSIMD LASX     HVX
MirrorUVRow_C         NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
MultiplyRow_16_C      SME     AVX512BW   RVV   WASMSIMD -        HVX
NV12ToARGBRow_C       SME     AVX512BW   RVV   WASMSIMD LASX     HVX
NV12ToRGB24Row_C      SME     AVX512VBMI RVV   -        -        -
NV12ToRGB565Row_C     NEON    AVX2       -     WASMSIMD LASX     -
NV21ToARGBRow_C       SME     AVX512BW   RVV   WASMSIMD LASX     HVX
NV21ToRGB24Row_C      SME     AVX512VBMI RVV   -        -        -
NV21ToYUV24Row_C      NEON    AVX2       -     -        -        -
P210ToAR30Row_C       SME     AVX2       -     -        -        -
P210ToARGBRow_C       SME     AVX2       -     -        -        -
P410ToAR30Row_C       SME     AVX2       -     -        -        -
P410ToARGBRow_C       SME     AVX2       -     -        -        -
RAWToARGBRow_C        SVE2    AVX512BW   RVV   WASMSIMD LASX     -
RAWToRGB24Row_C       SVE2    AVX512VBMI RVV   WASMSIMD LASX     -
RAWToRGBARow_C        SVE2    AVX512VBMI RVV   -        -        -
RGB24MirrorRow_C      NEON    AVX512VBMI -     WASMSIMD -        -
RGB24ToARGBRow_C      SVE2    AVX512BW   RVV   WASMSIMD LASX     -
RGB565ToARGBRow_C     NEON    AVX2       -     WASMSIMD LASX     -
RGB565ToUVMatrixRow_C NEON    AVX2       -     WASMSIMD -        -
RGB565ToUVRow_C       NEON    -          -     -        LASX     -
RGB565ToYMatrixRow_C  NEON    AVX2       -     WASMSIMD -        -
RGB565ToYRow_C        NEON    -          -     -        LASX     -
RGBAToARGBRow_C       NEON    AVX512BW   RVV   WASMSIMD LASX     HVX
RGBColorTableRow_C    NEON    X86        -     -        -        -
RGBToUV444MatrixRow_C NEON    AVX512BW   RVV   WASMSIMD -        -
RGBToUVMatrixRow_C    NEON    AVX512BW   RVV   WASMSIMD -        -
RGBToYMatrixRow_C     DOTPROD AVX512BW   RVV   WASMSIMD LASX     -
SetRow_C              NEON    ERMS       -     -        LASX     HVX
SobelRow_C            NEON    SSE2       -     -        LASX     -
SobelToPlaneRow_C     NEON    SSE2       -     -        LASX     -
SobelXRow_C           NEON    SSE2       -     -        -        -
SobelXYRow_C          NEON    SSE2       -     -        LASX     -
SobelYRow_C           NEON    SSE2       -     -        -        -
SplitARGBRow_C        NEON    AVX2       RVV   -        -        HVX
SplitRGBRow_C         NEON    AVX2       RVV   -        -        -
SplitUVRow_C          SVE2    AVX512BW   RVV   -        LASX     HVX
SplitUVRow_16_C       NEON    AVX2       -     -        -        HVX
SplitXRGBRow_C        NEON    AVX2       RVV   -        -        HVX
SwapUVRow_C           NEON    AVX512BW   RVV   WASMSIMD -        HVX
UYVYToARGBRow_C       SME     AVX2       -     -        LASX     -
UYVYToUV422Row_C      NEON    AVX2       -     -        LASX     HVX
UYVYToUVRow_C         SVE2    AVX2       -     -        LASX     HVX
UYVYToYRow_C          SVE2    AVX2       -     -        LASX     HVX
YUY2ToARGBRow_C       SME     AVX2       -     -        LASX     -
YUY2ToNVUVRow_C       NEON    AVX2       -     -        -        -
YUY2ToUV422Row_C      NEON    AVX2       -     -        LASX     HVX
YUY2ToUVRow_C         SVE2    AVX2       -     -        LASX     HVX
YUY2ToYRow_C          SVE2    AVX2       -     -        LASX     HVX
------------------------------------------------------------------------
SIMD (164/164 100%)   164 100% 154 94%   64 39% 56 34%   73 45%   64 39%
------------------------------------------------------------------------

Test: libyuv_unittest --gtest_filter=*AR30*:*Affine*:*ColorTable*:*CopyAlpha*:*Polynomial*:*Unattenuate*:*MirrorPlane_16*
Bug: None
Change-Id: Ib8b68beb77b47de6b996d41fd080397c61539ffb
This commit is contained in:
Frank Barchard 2026-10-27 14:37:21 -07:00
parent f506767c5f
commit be0b20bda0
10 changed files with 1105 additions and 5 deletions

View File

@ -1,6 +1,6 @@
Name: libyuv Name: libyuv
URL: https://chromium.googlesource.com/libyuv/libyuv/ URL: https://chromium.googlesource.com/libyuv/libyuv/
Version: 1975 Version: 1976
Revision: DEPS Revision: DEPS
License: BSD-3-Clause License: BSD-3-Clause
License File: LICENSE License File: LICENSE

View File

@ -540,6 +540,9 @@ extern "C" {
#if !defined(LIBYUV_DISABLE_NEON) && \ #if !defined(LIBYUV_DISABLE_NEON) && \
(defined(__aarch64__) || defined(__ARM_NEON__) || defined(LIBYUV_NEON)) (defined(__aarch64__) || defined(__ARM_NEON__) || defined(LIBYUV_NEON))
#define HAS_AB64TOARGBROW_NEON #define HAS_AB64TOARGBROW_NEON
#define HAS_AR30TOAB30ROW_NEON
#define HAS_AR30TOABGRROW_NEON
#define HAS_AR30TOARGBROW_NEON
#define HAS_AR64TOARGBROW_NEON #define HAS_AR64TOARGBROW_NEON
#define HAS_ARGB1555TOARGBROW_NEON #define HAS_ARGB1555TOARGBROW_NEON
#define HAS_ARGB1555TOUVROW_NEON #define HAS_ARGB1555TOUVROW_NEON
@ -547,6 +550,7 @@ extern "C" {
#define HAS_ARGB4444TOARGBROW_NEON #define HAS_ARGB4444TOARGBROW_NEON
#define HAS_ARGB4444TOUVROW_NEON #define HAS_ARGB4444TOUVROW_NEON
#define HAS_ARGB4444TOYROW_NEON #define HAS_ARGB4444TOYROW_NEON
#define HAS_ARGBCOPYALPHAROW_NEON
#define HAS_ARGBCOPYYTOALPHAROW_NEON #define HAS_ARGBCOPYYTOALPHAROW_NEON
#define HAS_ARGBEXTRACTALPHAROW_NEON #define HAS_ARGBEXTRACTALPHAROW_NEON
#define HAS_ARGBSETROW_NEON #define HAS_ARGBSETROW_NEON
@ -578,6 +582,7 @@ extern "C" {
#define HAS_CONVERT16TO8ROW_NEON #define HAS_CONVERT16TO8ROW_NEON
#define HAS_CONVERT8TO16ROW_NEON #define HAS_CONVERT8TO16ROW_NEON
#define HAS_CONVERT8TO8ROW_NEON #define HAS_CONVERT8TO8ROW_NEON
#define HAS_COPYROW_16_NEON
#define HAS_COPYROW_NEON #define HAS_COPYROW_NEON
#define HAS_DETILEROW_16_NEON #define HAS_DETILEROW_16_NEON
#define HAS_DETILEROW_NEON #define HAS_DETILEROW_NEON
@ -614,6 +619,7 @@ extern "C" {
#define HAS_MERGEXR64ROW_NEON #define HAS_MERGEXR64ROW_NEON
#define HAS_MERGEXRGB16TO8ROW_NEON #define HAS_MERGEXRGB16TO8ROW_NEON
#define HAS_MERGEXRGBROW_NEON #define HAS_MERGEXRGBROW_NEON
#define HAS_MIRRORROW_16_NEON
#define HAS_MIRRORROW_NEON #define HAS_MIRRORROW_NEON
#define HAS_MIRRORSPLITUVROW_NEON #define HAS_MIRRORSPLITUVROW_NEON
#define HAS_MIRRORUVROW_NEON #define HAS_MIRRORUVROW_NEON
@ -652,21 +658,27 @@ extern "C" {
// Effects: // Effects:
#define HAS_ARGBADDROW_NEON #define HAS_ARGBADDROW_NEON
#define HAS_ARGBAFFINEROW_NEON
#define HAS_ARGBALPHABLENDROW_NEON #define HAS_ARGBALPHABLENDROW_NEON
#define HAS_ARGBATTENUATEROW_NEON #define HAS_ARGBATTENUATEROW_NEON
#define HAS_ARGBBLENDROW_NEON #define HAS_ARGBBLENDROW_NEON
#define HAS_BLENDPLANEROW_NEON #define HAS_BLENDPLANEROW_NEON
#define HAS_ARGBCOLORMATRIXROW_NEON #define HAS_ARGBCOLORMATRIXROW_NEON
#define HAS_ARGBCOLORTABLEROW_NEON
#define HAS_ARGBGRAYROW_NEON #define HAS_ARGBGRAYROW_NEON
#define HAS_ARGBLUMACOLORTABLEROW_NEON
#define HAS_ARGBMIRRORROW_NEON #define HAS_ARGBMIRRORROW_NEON
#define HAS_ARGBMULTIPLYROW_NEON #define HAS_ARGBMULTIPLYROW_NEON
#define HAS_ARGBORROW_NEON #define HAS_ARGBORROW_NEON
#define HAS_ARGBPOLYNOMIALROW_NEON
#define HAS_ARGBQUANTIZEROW_NEON #define HAS_ARGBQUANTIZEROW_NEON
#define HAS_ARGBSEPIAROW_NEON #define HAS_ARGBSEPIAROW_NEON
#define HAS_ARGBSHADEROW_NEON #define HAS_ARGBSHADEROW_NEON
#define HAS_ARGBSHUFFLEROW_NEON #define HAS_ARGBSHUFFLEROW_NEON
#define HAS_ARGBSUBTRACTROW_NEON #define HAS_ARGBSUBTRACTROW_NEON
#define HAS_ARGBUNATTENUATEROW_NEON
#define HAS_RGB24MIRRORROW_NEON #define HAS_RGB24MIRRORROW_NEON
#define HAS_RGBCOLORTABLEROW_NEON
#define HAS_SOBELROW_NEON #define HAS_SOBELROW_NEON
#define HAS_SOBELTOPLANEROW_NEON #define HAS_SOBELTOPLANEROW_NEON
#define HAS_SOBELXROW_NEON #define HAS_SOBELXROW_NEON
@ -2838,6 +2850,10 @@ void MirrorSplitUVRow_C(const uint8_t* src_uv,
void MirrorRow_16_C(const uint16_t* src, uint16_t* dst, int width); void MirrorRow_16_C(const uint16_t* src, uint16_t* dst, int width);
void MirrorRow_16_AVX512BW(const uint16_t* src, uint16_t* dst, int width); void MirrorRow_16_AVX512BW(const uint16_t* src, uint16_t* dst, int width);
void MirrorRow_16_NEON(const uint16_t* src, uint16_t* dst, int width);
void MirrorRow_16_Any_NEON(const uint16_t* src_ptr,
uint16_t* dst_ptr,
int width);
void ARGBMirrorRow_AVX2(const uint8_t* src, uint8_t* dst, int width); void ARGBMirrorRow_AVX2(const uint8_t* src, uint8_t* dst, int width);
void ARGBMirrorRow_AVX512BW(const uint8_t* src, uint8_t* dst, int width); void ARGBMirrorRow_AVX512BW(const uint8_t* src, uint8_t* dst, int width);
@ -4014,16 +4030,22 @@ void CopyRow_Any_LSX(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void CopyRow_Any_LASX(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void CopyRow_Any_LASX(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void CopyRow_16_C(const uint16_t* src, uint16_t* dst, int count); void CopyRow_16_C(const uint16_t* src, uint16_t* dst, int count);
void CopyRow_16_NEON(const uint16_t* src, uint16_t* dst, int count);
void CopyRow_16_Any_NEON(const uint16_t* src_ptr, uint16_t* dst_ptr, int width);
void ARGBCopyAlphaRow_C(const uint8_t* src, uint8_t* dst, int width); void ARGBCopyAlphaRow_C(const uint8_t* src, uint8_t* dst, int width);
void ARGBCopyAlphaRow_SSE2(const uint8_t* src, uint8_t* dst, int width); void ARGBCopyAlphaRow_SSE2(const uint8_t* src, uint8_t* dst, int width);
void ARGBCopyAlphaRow_AVX2(const uint8_t* src, uint8_t* dst, int width); void ARGBCopyAlphaRow_AVX2(const uint8_t* src, uint8_t* dst, int width);
void ARGBCopyAlphaRow_NEON(const uint8_t* src, uint8_t* dst, int width);
void ARGBCopyAlphaRow_Any_SSE2(const uint8_t* src_ptr, void ARGBCopyAlphaRow_Any_SSE2(const uint8_t* src_ptr,
uint8_t* dst_ptr, uint8_t* dst_ptr,
int width); int width);
void ARGBCopyAlphaRow_Any_AVX2(const uint8_t* src_ptr, void ARGBCopyAlphaRow_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr, uint8_t* dst_ptr,
int width); int width);
void ARGBCopyAlphaRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ARGBExtractAlphaRow_C(const uint8_t* src_argb, uint8_t* dst_a, int width); void ARGBExtractAlphaRow_C(const uint8_t* src_argb, uint8_t* dst_a, int width);
void ARGBExtractAlphaRow_SSE2(const uint8_t* src_argb, void ARGBExtractAlphaRow_SSE2(const uint8_t* src_argb,
@ -4279,6 +4301,18 @@ void AR30ToAB30Row_C(const uint8_t* src_ar30, uint8_t* dst_ab30, int width);
void AR30ToAB30Row_AVX512BW(const uint8_t* src_ar30, void AR30ToAB30Row_AVX512BW(const uint8_t* src_ar30,
uint8_t* dst_ab30, uint8_t* dst_ab30,
int width); int width);
void AR30ToARGBRow_NEON(const uint8_t* src_ar30, uint8_t* dst_argb, int width);
void AR30ToABGRRow_NEON(const uint8_t* src_ar30, uint8_t* dst_abgr, int width);
void AR30ToAB30Row_NEON(const uint8_t* src_ar30, uint8_t* dst_ab30, int width);
void AR30ToARGBRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void AR30ToABGRRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void AR30ToAB30Row_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void RGB24ToARGBRow_Any_SSSE3(const uint8_t* src_ptr, void RGB24ToARGBRow_Any_SSSE3(const uint8_t* src_ptr,
uint8_t* dst_ptr, uint8_t* dst_ptr,
@ -6928,12 +6962,18 @@ void ARGBUnattenuateRow_SSE2(const uint8_t* src_argb,
void ARGBUnattenuateRow_AVX2(const uint8_t* src_argb, void ARGBUnattenuateRow_AVX2(const uint8_t* src_argb,
uint8_t* dst_argb, uint8_t* dst_argb,
int width); int width);
void ARGBUnattenuateRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
int width);
void ARGBUnattenuateRow_Any_SSE2(const uint8_t* src_ptr, void ARGBUnattenuateRow_Any_SSE2(const uint8_t* src_ptr,
uint8_t* dst_ptr, uint8_t* dst_ptr,
int width); int width);
void ARGBUnattenuateRow_Any_AVX2(const uint8_t* src_ptr, void ARGBUnattenuateRow_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr, uint8_t* dst_ptr,
int width); int width);
void ARGBUnattenuateRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ARGBGrayRow_C(const uint8_t* src_argb, uint8_t* dst_argb, int width); void ARGBGrayRow_C(const uint8_t* src_argb, uint8_t* dst_argb, int width);
void ARGBGrayRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_argb, int width); void ARGBGrayRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_argb, int width);
@ -6988,6 +7028,9 @@ void ARGBColorTableRow_C(uint8_t* dst_argb,
void ARGBColorTableRow_X86(uint8_t* dst_argb, void ARGBColorTableRow_X86(uint8_t* dst_argb,
const uint8_t* table_argb, const uint8_t* table_argb,
int width); int width);
void ARGBColorTableRow_NEON(uint8_t* dst_argb,
const uint8_t* table_argb,
int width);
void RGBColorTableRow_C(uint8_t* dst_argb, void RGBColorTableRow_C(uint8_t* dst_argb,
const uint8_t* table_argb, const uint8_t* table_argb,
@ -6995,6 +7038,9 @@ void RGBColorTableRow_C(uint8_t* dst_argb,
void RGBColorTableRow_X86(uint8_t* dst_argb, void RGBColorTableRow_X86(uint8_t* dst_argb,
const uint8_t* table_argb, const uint8_t* table_argb,
int width); int width);
void RGBColorTableRow_NEON(uint8_t* dst_argb,
const uint8_t* table_argb,
int width);
void ARGBQuantizeRow_C(uint8_t* dst_argb, void ARGBQuantizeRow_C(uint8_t* dst_argb,
int scale, int scale,
@ -7098,6 +7144,12 @@ void ARGBAffineRow_SSE2(const uint8_t* src_argb,
uint8_t* dst_argb, uint8_t* dst_argb,
const float* src_dudv, const float* src_dudv,
int width); int width);
LIBYUV_API
void ARGBAffineRow_NEON(const uint8_t* src_argb,
int src_argb_stride,
uint8_t* dst_argb,
const float* src_dudv,
int width);
// Used for I420Scale, ARGBScale, and ARGBInterpolate. // Used for I420Scale, ARGBScale, and ARGBInterpolate.
void InterpolateRow_C(uint8_t* dst_ptr, void InterpolateRow_C(uint8_t* dst_ptr,
@ -7351,6 +7403,14 @@ void ARGBPolynomialRow_AVX2(const uint8_t* src_argb,
uint8_t* dst_argb, uint8_t* dst_argb,
const float* poly, const float* poly,
int width); int width);
void ARGBPolynomialRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
const float* poly,
int width);
void ARGBPolynomialRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
const float* param,
int width);
// Scale and convert to half float. // Scale and convert to half float.
void HalfFloatRow_C(const uint16_t* src, uint16_t* dst, float scale, int width); void HalfFloatRow_C(const uint16_t* src, uint16_t* dst, float scale, int width);
@ -7442,6 +7502,11 @@ void ARGBLumaColorTableRow_SSSE3(const uint8_t* src_argb,
int width, int width,
const uint8_t* luma, const uint8_t* luma,
uint32_t lumacoeff); uint32_t lumacoeff);
void ARGBLumaColorTableRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
int width,
const uint8_t* luma,
uint32_t lumacoeff);
float ScaleMaxSamples_C(const float* src, float* dst, float scale, int width); float ScaleMaxSamples_C(const float* src, float* dst, float scale, int width);
float ScaleMaxSamples_NEON(const float* src, float ScaleMaxSamples_NEON(const float* src,

View File

@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ #ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1975 #define LIBYUV_VERSION 1976
#endif // INCLUDE_LIBYUV_VERSION_H_ #endif // INCLUDE_LIBYUV_VERSION_H_

View File

@ -3538,6 +3538,14 @@ static int AR30ToI420Matrix(const uint8_t* src_ar30,
src_ar30 = src_ar30 + (ptrdiff_t)(height - 1) * src_stride_ar30; src_ar30 = src_ar30 + (ptrdiff_t)(height - 1) * src_stride_ar30;
src_stride_ar30 = -src_stride_ar30; src_stride_ar30 = -src_stride_ar30;
} }
#if defined(HAS_AR30TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
AR30ToARGBRow = AR30ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
AR30ToARGBRow = AR30ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_AR30TOARGBROW_AVX512BW) #if defined(HAS_AR30TOARGBROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW)) { if (TestCpuFlag(kCpuHasAVX512BW)) {
AR30ToARGBRow = AR30ToARGBRow_AVX512BW; AR30ToARGBRow = AR30ToARGBRow_AVX512BW;

View File

@ -4522,6 +4522,14 @@ int AR30ToARGB(const uint8_t* src_ar30,
} }
void (*AR30ToARGBRow)(const uint8_t* src_ar30, uint8_t* dst_argb, int width) = void (*AR30ToARGBRow)(const uint8_t* src_ar30, uint8_t* dst_argb, int width) =
AR30ToARGBRow_C; AR30ToARGBRow_C;
#if defined(HAS_AR30TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
AR30ToARGBRow = AR30ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
AR30ToARGBRow = AR30ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_AR30TOARGBROW_AVX512BW) #if defined(HAS_AR30TOARGBROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW)) { if (TestCpuFlag(kCpuHasAVX512BW)) {
AR30ToARGBRow = AR30ToARGBRow_AVX512BW; AR30ToARGBRow = AR30ToARGBRow_AVX512BW;
@ -4563,6 +4571,14 @@ int AR30ToABGR(const uint8_t* src_ar30,
height = 1; height = 1;
src_stride_ar30 = dst_stride_abgr = 0; src_stride_ar30 = dst_stride_abgr = 0;
} }
#if defined(HAS_AR30TOABGRROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
AR30ToABGRRow = AR30ToABGRRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
AR30ToABGRRow = AR30ToABGRRow_NEON;
}
}
#endif
#if defined(HAS_AR30TOABGRROW_AVX512BW) #if defined(HAS_AR30TOABGRROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW)) { if (TestCpuFlag(kCpuHasAVX512BW)) {
AR30ToABGRRow = AR30ToABGRRow_AVX512BW; AR30ToABGRRow = AR30ToABGRRow_AVX512BW;
@ -4604,6 +4620,14 @@ int AR30ToAB30(const uint8_t* src_ar30,
height = 1; height = 1;
src_stride_ar30 = dst_stride_ab30 = 0; src_stride_ar30 = dst_stride_ab30 = 0;
} }
#if defined(HAS_AR30TOAB30ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
AR30ToAB30Row = AR30ToAB30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
AR30ToAB30Row = AR30ToAB30Row_NEON;
}
}
#endif
#if defined(HAS_AR30TOAB30ROW_AVX512BW) #if defined(HAS_AR30TOAB30ROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW)) { if (TestCpuFlag(kCpuHasAVX512BW)) {
AR30ToAB30Row = AR30ToAB30Row_AVX512BW; AR30ToAB30Row = AR30ToAB30Row_AVX512BW;

View File

@ -2926,7 +2926,14 @@ void MirrorPlane_16(const uint16_t* src_y,
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y; src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_stride_y = -src_stride_y; src_stride_y = -src_stride_y;
} }
#if defined(HAS_MIRRORUVROW_NEON) #if defined(HAS_MIRRORROW_16_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MirrorRow_16 = MirrorRow_16_Any_NEON;
if (IS_ALIGNED(width, 16)) {
MirrorRow_16 = MirrorRow_16_NEON;
}
}
#elif defined(HAS_MIRRORUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) { if (TestCpuFlag(kCpuHasNEON)) {
MirrorRow_16 = reinterpret_cast<void (*)(const uint16_t*, uint16_t*, int)>( MirrorRow_16 = reinterpret_cast<void (*)(const uint16_t*, uint16_t*, int)>(
MirrorUVRow_Any_NEON); MirrorUVRow_Any_NEON);
@ -4693,7 +4700,14 @@ int ARGBUnattenuate(const uint8_t* src_argb,
} }
} }
#endif #endif
// TODO(fbarchard): Neon version. #if defined(HAS_ARGBUNATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBUnattenuateRow = ARGBUnattenuateRow_Any_NEON;
if (IS_ALIGNED(width, 4)) {
ARGBUnattenuateRow = ARGBUnattenuateRow_NEON;
}
}
#endif
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
ARGBUnattenuateRow(src_argb, dst_argb, width); ARGBUnattenuateRow(src_argb, dst_argb, width);
@ -5019,6 +5033,11 @@ int ARGBColorTable(uint8_t* dst_argb,
if (TestCpuFlag(kCpuHasX86)) { if (TestCpuFlag(kCpuHasX86)) {
ARGBColorTableRow = ARGBColorTableRow_X86; ARGBColorTableRow = ARGBColorTableRow_X86;
} }
#endif
#if defined(HAS_ARGBCOLORTABLEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBColorTableRow = ARGBColorTableRow_NEON;
}
#endif #endif
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
ARGBColorTableRow(dst, table_argb, width); ARGBColorTableRow(dst, table_argb, width);
@ -5055,6 +5074,11 @@ int RGBColorTable(uint8_t* dst_argb,
if (TestCpuFlag(kCpuHasX86)) { if (TestCpuFlag(kCpuHasX86)) {
RGBColorTableRow = RGBColorTableRow_X86; RGBColorTableRow = RGBColorTableRow_X86;
} }
#endif
#if defined(HAS_RGBCOLORTABLEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
RGBColorTableRow = RGBColorTableRow_NEON;
}
#endif #endif
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
RGBColorTableRow(dst, table_argb, width); RGBColorTableRow(dst, table_argb, width);
@ -6224,6 +6248,14 @@ int ARGBPolynomial(const uint8_t* src_argb,
ARGBPolynomialRow = ARGBPolynomialRow_AVX2; ARGBPolynomialRow = ARGBPolynomialRow_AVX2;
} }
#endif #endif
#if defined(HAS_ARGBPOLYNOMIALROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBPolynomialRow = ARGBPolynomialRow_Any_NEON;
if (IS_ALIGNED(width, 2)) {
ARGBPolynomialRow = ARGBPolynomialRow_NEON;
}
}
#endif
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
ARGBPolynomialRow(src_argb, dst_argb, poly, width); ARGBPolynomialRow(src_argb, dst_argb, poly, width);
@ -6383,6 +6415,11 @@ int ARGBLumaColorTable(const uint8_t* src_argb,
ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3; ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3;
} }
#endif #endif
#if defined(HAS_ARGBLUMACOLORTABLEROW_NEON)
if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 4)) {
ARGBLumaColorTableRow = ARGBLumaColorTableRow_NEON;
}
#endif
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
ARGBLumaColorTableRow(src_argb, dst_argb, width, luma, 0x00264b0f); ARGBLumaColorTableRow(src_argb, dst_argb, width, luma, 0x00264b0f);
@ -6420,6 +6457,14 @@ int ARGBCopyAlpha(const uint8_t* src_argb,
height = 1; height = 1;
src_stride_argb = dst_stride_argb = 0; src_stride_argb = dst_stride_argb = 0;
} }
#if defined(HAS_ARGBCOPYALPHAROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBCopyAlphaRow = ARGBCopyAlphaRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBCopyAlphaRow = ARGBCopyAlphaRow_NEON;
}
}
#endif
#if defined(HAS_ARGBCOPYALPHAROW_SSE2) #if defined(HAS_ARGBCOPYALPHAROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) { if (TestCpuFlag(kCpuHasSSE2)) {
ARGBCopyAlphaRow = ARGBCopyAlphaRow_Any_SSE2; ARGBCopyAlphaRow = ARGBCopyAlphaRow_Any_SSE2;

View File

@ -1105,6 +1105,15 @@ ANY11(ABGRToAR30Row_Any_NEON, ABGRToAR30Row_NEON, 0, 4, 4, 7)
#if defined(HAS_ARGBTOAR30ROW_NEON) #if defined(HAS_ARGBTOAR30ROW_NEON)
ANY11(ARGBToAR30Row_Any_NEON, ARGBToAR30Row_NEON, 0, 4, 4, 7) ANY11(ARGBToAR30Row_Any_NEON, ARGBToAR30Row_NEON, 0, 4, 4, 7)
#endif #endif
#if defined(HAS_AR30TOARGBROW_NEON)
ANY11(AR30ToARGBRow_Any_NEON, AR30ToARGBRow_NEON, 0, 4, 4, 7)
#endif
#if defined(HAS_AR30TOABGRROW_NEON)
ANY11(AR30ToABGRRow_Any_NEON, AR30ToABGRRow_NEON, 0, 4, 4, 7)
#endif
#if defined(HAS_AR30TOAB30ROW_NEON)
ANY11(AR30ToAB30Row_Any_NEON, AR30ToAB30Row_NEON, 0, 4, 4, 7)
#endif
#if defined(HAS_ARGBTOAR30ROW_SSSE3) #if defined(HAS_ARGBTOAR30ROW_SSSE3)
ANY11(ARGBToAR30Row_Any_SSSE3, ARGBToAR30Row_SSSE3, 0, 4, 4, 3) ANY11(ARGBToAR30Row_Any_SSSE3, ARGBToAR30Row_SSSE3, 0, 4, 4, 3)
#endif #endif
@ -1330,6 +1339,9 @@ ANY11(ARGBUnattenuateRow_Any_AVX2, ARGBUnattenuateRow_AVX2, 0, 4, 4, 7)
#ifdef HAS_ARGBATTENUATEROW_NEON #ifdef HAS_ARGBATTENUATEROW_NEON
ANY11(ARGBAttenuateRow_Any_NEON, ARGBAttenuateRow_NEON, 0, 4, 4, 7) ANY11(ARGBAttenuateRow_Any_NEON, ARGBAttenuateRow_NEON, 0, 4, 4, 7)
#endif #endif
#ifdef HAS_ARGBUNATTENUATEROW_NEON
ANY11(ARGBUnattenuateRow_Any_NEON, ARGBUnattenuateRow_NEON, 0, 4, 4, 3)
#endif
#ifdef HAS_ARGBATTENUATEROW_LSX #ifdef HAS_ARGBATTENUATEROW_LSX
ANY11(ARGBAttenuateRow_Any_LSX, ARGBAttenuateRow_LSX, 0, 4, 4, 3) ANY11(ARGBAttenuateRow_Any_LSX, ARGBAttenuateRow_LSX, 0, 4, 4, 3)
#endif #endif
@ -1419,6 +1431,9 @@ ANY11B(ARGBCopyAlphaRow_Any_AVX2, ARGBCopyAlphaRow_AVX2, 0, 4, 4, 15)
#ifdef HAS_ARGBCOPYALPHAROW_SSE2 #ifdef HAS_ARGBCOPYALPHAROW_SSE2
ANY11B(ARGBCopyAlphaRow_Any_SSE2, ARGBCopyAlphaRow_SSE2, 0, 4, 4, 7) ANY11B(ARGBCopyAlphaRow_Any_SSE2, ARGBCopyAlphaRow_SSE2, 0, 4, 4, 7)
#endif #endif
#ifdef HAS_ARGBCOPYALPHAROW_NEON
ANY11B(ARGBCopyAlphaRow_Any_NEON, ARGBCopyAlphaRow_NEON, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2 #ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2
ANY11B(ARGBCopyYToAlphaRow_Any_AVX2, ARGBCopyYToAlphaRow_AVX2, 0, 1, 4, 15) ANY11B(ARGBCopyYToAlphaRow_Any_AVX2, ARGBCopyYToAlphaRow_AVX2, 0, 1, 4, 15)
#endif #endif
@ -1578,6 +1593,14 @@ ANY11P(ARGBOrRow_Any_LASX, ARGBOrRow_LASX, const uint32_t, 4, 4, 7)
#ifdef HAS_ARGBORROW_WASMSIMD #ifdef HAS_ARGBORROW_WASMSIMD
ANY11P(ARGBOrRow_Any_WASMSIMD, ARGBOrRow_WASMSIMD, const uint32_t, 4, 4, 3) ANY11P(ARGBOrRow_Any_WASMSIMD, ARGBOrRow_WASMSIMD, const uint32_t, 4, 4, 3)
#endif #endif
#ifdef HAS_ARGBPOLYNOMIALROW_NEON
ANY11P(ARGBPolynomialRow_Any_NEON,
ARGBPolynomialRow_NEON,
const float*,
4,
4,
1)
#endif
#undef ANY11P #undef ANY11P
#undef ANY11P #undef ANY11P
@ -1647,6 +1670,10 @@ ANY11T(AR64ToARGBRow_Any_NEON, AR64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
ANY11T(AB64ToARGBRow_Any_NEON, AB64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7) ANY11T(AB64ToARGBRow_Any_NEON, AB64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
#endif #endif
#ifdef HAS_COPYROW_16_NEON
ANY11T(CopyRow_16_Any_NEON, CopyRow_16_NEON, 2, 2, uint16_t, uint16_t, 15)
#endif
#undef ANY11T #undef ANY11T
// Any 1 to 1 with parameter and shorts. BPP measures in shorts. // Any 1 to 1 with parameter and shorts. BPP measures in shorts.
@ -2196,6 +2223,31 @@ ANY11M(RGB24MirrorRow_Any_WASMSIMD, RGB24MirrorRow_WASMSIMD, 3, 15)
#endif #endif
#undef ANY11M #undef ANY11M
// Any 1 to 1 mirror with type.
#define ANY11MT(NAMEANY, ANY_SIMD, T, BPP, MASK) \
void NAMEANY(const T* src_ptr, T* dst_ptr, int width) { \
SIMD_ALIGNED(T vin[64]); \
static_assert((MASK + 1) * BPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(T vout[64]); \
static_assert((MASK + 1) * BPP <= sizeof(vout), "vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(src_ptr + r, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr, r * BPP); \
ANY_SIMD(vin, vout, MASK + 1); \
memcpy(dst_ptr + np, vout + (MASK + 1 - r), r * BPP); \
}
#ifdef HAS_MIRRORROW_16_NEON
ANY11MT(MirrorRow_16_Any_NEON, MirrorRow_16_NEON, uint16_t, 2, 15)
#endif
#undef ANY11MT
// Any 1 plane. (memset) // Any 1 plane. (memset)
#define ANY1(NAMEANY, ANY_SIMD, T, BPP, MASK) \ #define ANY1(NAMEANY, ANY_SIMD, T, BPP, MASK) \
void NAMEANY(uint8_t* dst_ptr, T v32, int width) { \ void NAMEANY(uint8_t* dst_ptr, T v32, int width) { \

View File

@ -3992,6 +3992,433 @@ void Convert8To16Row_NEON(const uint8_t* src_y,
: "cc", "memory", "q0", "q1", "q2"); : "cc", "memory", "q0", "q1", "q2");
} }
void CopyRow_16_NEON(const uint16_t* src, uint16_t* dst, int count) {
asm volatile(
"1: \n"
"vld1.16 {d0, d1, d2, d3}, [%0]! \n" // load 16
"subs %2, %2, #16 \n" // 16 processed per loop
"vst1.16 {d0, d1, d2, d3}, [%1]! \n" // store 16
"bgt 1b \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(count) // %2
:
: "memory", "cc", "q0", "q1");
}
void MirrorRow_16_NEON(const uint16_t* src, uint16_t* dst, int width) {
asm volatile(
// Start at end of source row.
"add %0, %0, %2, lsl #1 \n"
"sub %0, %0, #32 \n" // 32 bytes per loop
"1: \n"
"vld1.16 {q1, q2}, [%0], %3 \n" // src -= 32
"subs %2, %2, #16 \n" // 16 pixels per loop.
"vrev64.16 q0, q2 \n"
"vrev64.16 q1, q1 \n"
"vswp d0, d1 \n"
"vswp d2, d3 \n"
"vst1.16 {q0, q1}, [%1]! \n" // dst += 32
"bgt 1b \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
: "r"(-32) // %3
: "memory", "cc", "q0", "q1", "q2");
}
void AR30ToARGBRow_NEON(const uint8_t* src_ar30, uint8_t* dst_argb, int width) {
asm volatile(
"vmov.i32 q8, #0x0000ff00 \n"
"vmov.i32 q9, #0x000fffff \n"
"vshl.i32 q9, q9, #8 \n" // 0x0fffff00
"1: \n"
"vld1.8 {q0, q1}, [%0]! \n" // load 8 AR30 pixels
"subs %2, %2, #8 \n" // 8 pixels per loop
"vsri.32 q0, q0, #2 \n"
"vsri.32 q1, q1, #2 \n"
"vshr.u32 q2, q0, #2 \n"
"vshr.u32 q3, q1, #2 \n"
"vshr.u32 q4, q0, #4 \n"
"vshr.u32 q5, q1, #4 \n"
"vbit q0, q4, q9 \n"
"vbit q1, q5, q9 \n"
"vbit q0, q2, q8 \n"
"vbit q1, q3, q8 \n"
"vst1.8 {q0, q1}, [%1]! \n" // store 8 ARGB pixels
"bgt 1b \n"
: "+r"(src_ar30), // %0
"+r"(dst_argb), // %1
"+r"(width) // %2
:
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q8", "q9");
}
void AR30ToABGRRow_NEON(const uint8_t* src_ar30, uint8_t* dst_abgr, int width) {
asm volatile(
"vmov.i64 q8, #0x00ffff0000ffff00 \n"
"1: \n"
"vld1.8 {q0, q1}, [%0]! \n" // load 8 AR30 pixels
"subs %2, %2, #8 \n" // 8 pixels per loop
"vsri.32 q0, q0, #2 \n"
"vsri.32 q1, q1, #2 \n"
"vshr.u32 q2, q0, #2 \n"
"vshr.u32 q3, q1, #2 \n"
"vsli.32 q2, q0, #16 \n"
"vsli.32 q3, q1, #16 \n"
"vsri.32 q0, q0, #4 \n"
"vsri.32 q1, q1, #4 \n"
"vsri.32 q0, q0, #16 \n"
"vsri.32 q1, q1, #16 \n"
"vbit q0, q2, q8 \n"
"vbit q1, q3, q8 \n"
"vst1.8 {q0, q1}, [%1]! \n" // store 8 ABGR pixels
"bgt 1b \n"
: "+r"(src_ar30), // %0
"+r"(dst_abgr), // %1
"+r"(width) // %2
:
: "memory", "cc", "q0", "q1", "q2", "q3", "q8");
}
void AR30ToAB30Row_NEON(const uint8_t* src_ar30, uint8_t* dst_ab30, int width) {
asm volatile(
"vmov.i8 q9, #0xff \n"
"vshr.u32 q9, q9, #22 \n" // 0x000003ff
"vshl.i32 q8, q9, #20 \n" // 0x3ff00000
"1: \n"
"vld1.8 {q0, q1}, [%0]! \n" // load 8 AR30 pixels
"subs %2, %2, #8 \n" // 8 pixels per loop
"vshl.i32 q2, q0, #20 \n"
"vshl.i32 q3, q1, #20 \n"
"vshr.u32 q4, q0, #20 \n"
"vshr.u32 q5, q1, #20 \n"
"vbit q0, q2, q8 \n"
"vbit q1, q3, q8 \n"
"vbit q0, q4, q9 \n"
"vbit q1, q5, q9 \n"
"vst1.8 {q0, q1}, [%1]! \n" // store 8 AB30 pixels
"bgt 1b \n"
: "+r"(src_ar30), // %0
"+r"(dst_ab30), // %1
"+r"(width) // %2
:
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q8", "q9");
}
void ARGBCopyAlphaRow_NEON(const uint8_t* src, uint8_t* dst, int width) {
asm volatile(
"vmov.i32 q4, #0xff000000 \n"
"1: \n"
"vld1.8 {q0, q1}, [%0]! \n" // load 8 src pixels
"vld1.8 {q2, q3}, [%1] \n" // load 8 dst pixels
"subs %2, %2, #8 \n" // 8 pixels per loop
"vbit q2, q0, q4 \n"
"vbit q3, q1, q4 \n"
"vst1.8 {q2, q3}, [%1]! \n" // store 8 dst pixels
"bgt 1b \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
:
: "memory", "cc", "q0", "q1", "q2", "q3", "q4");
}
void ARGBUnattenuateRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
int width) {
uint32_t tmp, addr;
asm volatile(
"vmov.i32 q8, #0xff000000 \n"
"1: \n"
"ldrb %3, [%0, #3] \n"
"add %4, %5, %3, lsl #2 \n"
"vld1.16 {d6[0]}, [%4] \n"
"ldrb %3, [%0, #7] \n"
"add %4, %5, %3, lsl #2 \n"
"vld1.16 {d6[1]}, [%4] \n"
"ldrb %3, [%0, #11] \n"
"add %4, %5, %3, lsl #2 \n"
"vld1.16 {d6[2]}, [%4] \n"
"ldrb %3, [%0, #15] \n"
"add %4, %5, %3, lsl #2 \n"
"vld1.16 {d6[3]}, [%4] \n"
"vld1.8 {q0}, [%0]! \n"
"subs %2, %2, #4 \n"
"vmov q1, q0 \n"
"vmov q2, q0 \n"
"vzip.8 q1, q2 \n"
"vmull.u16 q4, d2, d6[0] \n"
"vmull.u16 q5, d3, d6[1] \n"
"vmull.u16 q6, d4, d6[2] \n"
"vmull.u16 q7, d5, d6[3] \n"
"vshrn.i32 d8, q4, #16 \n"
"vshrn.i32 d9, q5, #16 \n"
"vshrn.i32 d12, q6, #16 \n"
"vshrn.i32 d13, q7, #16 \n"
"vqmovn.u16 d2, q4 \n"
"vqmovn.u16 d3, q6 \n"
"vbit q1, q0, q8 \n"
"vst1.8 {q1}, [%1]! \n"
"bgt 1b \n"
: "+r"(src_argb), // %0
"+r"(dst_argb), // %1
"+r"(width), // %2
"=&r"(tmp), // %3
"=&r"(addr) // %4
: "r"(fixed_invtbl8) // %5
: "memory", "cc", "q0", "q1", "q2", "d6", "q4", "q5", "q6", "q7", "q8");
}
void ARGBPolynomialRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
const float* poly,
int width) {
asm volatile(
"vld1.32 {q8, q9}, [%3]! \n" // c0, c1
"vld1.32 {q10, q11}, [%3] \n" // c2, c3
"1: \n"
"vld1.8 {d0}, [%0]! \n" // load 2 pixels
"subs %2, %2, #2 \n" // 2 pixels per loop
"vmovl.u8 q0, d0 \n"
"vmovl.u16 q1, d0 \n"
"vmovl.u16 q2, d1 \n"
"vcvt.f32.u32 q1, q1 \n" // x0
"vcvt.f32.u32 q2, q2 \n" // x1
"vmov q3, q8 \n" // c0
"vmov q4, q8 \n" // c0
"vmla.f32 q3, q9, q1 \n" // c0 + c1 * x0
"vmla.f32 q4, q9, q2 \n" // c0 + c1 * x1
"vmul.f32 q5, q1, q1 \n" // x0 * x0
"vmul.f32 q6, q2, q2 \n" // x1 * x1
"vmla.f32 q3, q10, q5 \n" // + c2 * x0^2
"vmla.f32 q4, q10, q6 \n" // + c2 * x1^2
"vmul.f32 q5, q5, q1 \n" // x0^3
"vmul.f32 q6, q6, q2 \n" // x1^3
"vmla.f32 q3, q11, q5 \n" // + c3 * x0^3
"vmla.f32 q4, q11, q6 \n" // + c3 * x1^3
"vcvt.s32.f32 q3, q3 \n"
"vcvt.s32.f32 q4, q4 \n"
"vqmovn.s32 d6, q3 \n"
"vqmovn.s32 d7, q4 \n"
"vqmovun.s16 d6, q3 \n"
"vst1.8 {d6}, [%1]! \n"
"bgt 1b \n"
: "+r"(src_argb), // %0
"+r"(dst_argb), // %1
"+r"(width), // %2
"+r"(poly) // %3
:
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q8", "q9",
"q10", "q11");
}
void ARGBColorTableRow_NEON(uint8_t* dst_argb,
const uint8_t* table_argb,
int width) {
const uint8_t* table_g = table_argb + 1;
const uint8_t* table_r = table_argb + 2;
const uint8_t* table_a = table_argb + 3;
uint32_t b, g, r, a;
asm volatile(
"1: \n"
"ldrb %2, [%0] \n"
"ldrb %3, [%0, #1] \n"
"ldrb %4, [%0, #2] \n"
"ldrb %5, [%0, #3] \n"
"ldrb %2, [%6, %2, lsl #2] \n"
"ldrb %3, [%7, %3, lsl #2] \n"
"ldrb %4, [%8, %4, lsl #2] \n"
"ldrb %5, [%9, %5, lsl #2] \n"
"subs %1, %1, #1 \n"
"strb %2, [%0] \n"
"strb %3, [%0, #1] \n"
"strb %4, [%0, #2] \n"
"strb %5, [%0, #3] \n"
"add %0, %0, #4 \n"
"bgt 1b \n"
: "+r"(dst_argb), // %0
"+r"(width), // %1
"=&r"(b), // %2
"=&r"(g), // %3
"=&r"(r), // %4
"=&r"(a) // %5
: "r"(table_argb), // %6
"r"(table_g), // %7
"r"(table_r), // %8
"r"(table_a) // %9
: "memory", "cc");
}
void RGBColorTableRow_NEON(uint8_t* dst_argb,
const uint8_t* table_argb,
int width) {
const uint8_t* table_g = table_argb + 1;
const uint8_t* table_r = table_argb + 2;
uint32_t b, g, r;
asm volatile(
"1: \n"
"ldrb %2, [%0] \n"
"ldrb %3, [%0, #1] \n"
"ldrb %4, [%0, #2] \n"
"ldrb %2, [%5, %2, lsl #2] \n"
"ldrb %3, [%6, %3, lsl #2] \n"
"ldrb %4, [%7, %4, lsl #2] \n"
"subs %1, %1, #1 \n"
"strb %2, [%0] \n"
"strb %3, [%0, #1] \n"
"strb %4, [%0, #2] \n"
"add %0, %0, #4 \n"
"bgt 1b \n"
: "+r"(dst_argb), // %0
"+r"(width), // %1
"=&r"(b), // %2
"=&r"(g), // %3
"=&r"(r) // %4
: "r"(table_argb), // %5
"r"(table_g), // %6
"r"(table_r) // %7
: "memory", "cc");
}
void ARGBLumaColorTableRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
int width,
const uint8_t* luma,
uint32_t lumacoeff) {
uint32_t idx, addr;
asm volatile(
"vdup.32 q4, %6 \n" // lumacoeff
"1: \n"
"vld1.8 {q0}, [%0]! \n" // load 4 ARGB pixels
"subs %2, %2, #4 \n" // 4 pixels per loop
"vmull.u8 q1, d0, d8 \n"
"vmull.u8 q2, d1, d9 \n"
"vpadd.i16 d2, d2, d3 \n"
"vpadd.i16 d3, d4, d5 \n"
"vpadd.i16 d2, d2, d3 \n"
"vbic.i16 d2, #0x8000 \n" // clear bit 15
"vshrn.i16 d2, q1, #8 \n" // L_k & 0x7f
"vmov d3, d2 \n"
"vzip.8 d2, d3 \n"
"vmov d3, d2 \n"
"vzip.8 d2, d3 \n"
"vmov q2, q0 \n"
"vzip.8 q2, q1 \n" // q2: p0,1; q1: p2,3
"vmov.u16 %3, d4[0] \n"
"add %4, %5, %3 \n"
"vld1.8 {d0[0]}, [%4] \n"
"vmov.u16 %3, d4[1] \n"
"add %4, %5, %3 \n"
"vld1.8 {d0[1]}, [%4] \n"
"vmov.u16 %3, d4[2] \n"
"add %4, %5, %3 \n"
"vld1.8 {d0[2]}, [%4] \n"
"vmov.u16 %3, d5[0] \n"
"add %4, %5, %3 \n"
"vld1.8 {d0[4]}, [%4] \n"
"vmov.u16 %3, d5[1] \n"
"add %4, %5, %3 \n"
"vld1.8 {d0[5]}, [%4] \n"
"vmov.u16 %3, d5[2] \n"
"add %4, %5, %3 \n"
"vld1.8 {d0[6]}, [%4] \n"
"vmov.u16 %3, d2[0] \n"
"add %4, %5, %3 \n"
"vld1.8 {d1[0]}, [%4] \n"
"vmov.u16 %3, d2[1] \n"
"add %4, %5, %3 \n"
"vld1.8 {d1[1]}, [%4] \n"
"vmov.u16 %3, d2[2] \n"
"add %4, %5, %3 \n"
"vld1.8 {d1[2]}, [%4] \n"
"vmov.u16 %3, d3[0] \n"
"add %4, %5, %3 \n"
"vld1.8 {d1[4]}, [%4] \n"
"vmov.u16 %3, d3[1] \n"
"add %4, %5, %3 \n"
"vld1.8 {d1[5]}, [%4] \n"
"vmov.u16 %3, d3[2] \n"
"add %4, %5, %3 \n"
"vld1.8 {d1[6]}, [%4] \n"
"vst1.8 {q0}, [%1]! \n"
"bgt 1b \n"
: "+r"(src_argb), // %0
"+r"(dst_argb), // %1
"+r"(width), // %2
"=&r"(idx), // %3
"=&r"(addr) // %4
: "r"(luma), // %5
"r"(lumacoeff) // %6
: "memory", "cc", "q0", "q1", "q2", "q4");
}
void ARGBAffineRow_NEON(const uint8_t* src_argb,
int src_argb_stride,
uint8_t* dst_argb,
const float* uv_dudv,
int width) {
uint32_t off0, off1;
asm volatile(
"vld1.32 {d4, d5}, [%5] \n" // d4=[u,v], d5=[du,dv]
"vmov d12, d5 \n" // d12=[du,dv]
"vdup.32 d10, %4 \n" // [stride, stride]
"vmov.i32 d11, #4 \n" // [4, 4]
"vtrn.32 d11, d10 \n" // q5=[4, stride, 4,
// stride]
"subs %1, %1, #4 \n"
"blt 2f \n"
"vmov d13, d12 \n" // q6=[du, dv, du, dv]
"vadd.f32 q4, q6, q6 \n" // 2 * [du, dv, du, dv]
"vadd.f32 d5, d4, d12 \n" // [u+du, v+dv]
"vadd.f32 q3, q2, q4 \n" // [u+2du, v+2dv, u+3du,
// v+3dv]
"vadd.f32 q4, q4, q4 \n" // 4 * [du, dv, du, dv]
"1: \n"
"vcvt.s32.f32 q0, q2 \n"
"vcvt.s32.f32 q1, q3 \n"
"vadd.f32 q2, q2, q4 \n"
"vadd.f32 q3, q3, q4 \n"
"vmul.i32 q0, q0, q5 \n"
"vmul.i32 q1, q1, q5 \n"
"vpadd.i32 d14, d0, d1 \n"
"vpadd.i32 d15, d2, d3 \n"
"vmov %2, %3, d14 \n"
"ldr %2, [%6, %2] \n"
"ldr %3, [%6, %3] \n"
"str %2, [%0], #4 \n"
"str %3, [%0], #4 \n"
"vmov %2, %3, d15 \n"
"ldr %2, [%6, %2] \n"
"ldr %3, [%6, %3] \n"
"str %2, [%0], #4 \n"
"str %3, [%0], #4 \n"
"subs %1, %1, #4 \n"
"bge 1b \n"
"2: \n"
"adds %1, %1, #4 \n"
"beq 4f \n"
"3: \n"
"vcvt.s32.f32 d0, d4 \n"
"vadd.f32 d4, d4, d12 \n"
"vmul.i32 d0, d0, d10 \n"
"vpadd.i32 d0, d0, d0 \n"
"vmov.32 %2, d0[0] \n"
"ldr %2, [%6, %2] \n"
"str %2, [%0], #4 \n"
"subs %1, %1, #1 \n"
"bgt 3b \n"
"4: \n"
: "+r"(dst_argb), // %0
"+r"(width), // %1
"=&r"(off0), // %2
"=&r"(off1) // %3
: "r"(src_argb_stride), // %4
"r"(uv_dudv), // %5
"r"(src_argb) // %6
: "memory", "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7");
}
#endif // !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__).. #endif // !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__)..
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -5642,6 +5642,471 @@ void Convert8To16Row_NEON(const uint8_t* src_y,
: "cc", "memory", "v0", "v1", "v2"); : "cc", "memory", "v0", "v1", "v2");
} }
void CopyRow_16_NEON(const uint16_t* src, uint16_t* dst, int count) {
asm volatile(
"1: \n"
"ldp q0, q1, [%0], #32 \n"
"subs %w2, %w2, #16 \n" // 16 processed per loop
"stp q0, q1, [%1], #32 \n"
"b.gt 1b \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(count) // %2
:
: "memory", "cc", "v0", "v1");
}
void MirrorRow_16_NEON(const uint16_t* src, uint16_t* dst, int width) {
asm volatile(
// Start at end of source row.
"ld1 {v4.16b}, [%3] \n" // shuffler
"add %0, %0, %w2, sxtw #1 \n"
"sub %0, %0, #32 \n"
"1: \n"
"ldr q1, [%0, 16] \n"
"ldr q0, [%0], -32 \n" // src -= 32
"subs %w2, %w2, #16 \n" // 16 pixels per loop.
"tbl v2.16b, {v1.16b}, v4.16b \n"
"tbl v3.16b, {v0.16b}, v4.16b \n"
"stp q2, q3, [%1], #32 \n" // dst += 32
"b.gt 1b \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
: "r"(&kShuffleMirrorUV) // %3
: "memory", "cc", "v0", "v1", "v2", "v3", "v4");
}
void AR30ToARGBRow_NEON(const uint8_t* src_ar30, uint8_t* dst_argb, int width) {
asm volatile(
"movi v16.4s, #0xff, lsl #8 \n" // 0x0000ff00
"movi v17.4s, #0x0f, msl #16 \n" // 0x000fffff
"shl v17.4s, v17.4s, #8 \n" // 0x0fffff00
"1: \n"
"ldp q0, q1, [%0], #32 \n" // load 8 AR30 pixels
"subs %w2, %w2, #8 \n" // 8 pixels per loop
"sri v0.4s, v0.4s, #2 \n"
"sri v1.4s, v1.4s, #2 \n"
"ushr v2.4s, v0.4s, #2 \n"
"ushr v3.4s, v1.4s, #2 \n"
"ushr v4.4s, v0.4s, #4 \n"
"ushr v5.4s, v1.4s, #4 \n"
"bit v0.16b, v4.16b, v17.16b \n"
"bit v1.16b, v5.16b, v17.16b \n"
"bit v0.16b, v2.16b, v16.16b \n"
"bit v1.16b, v3.16b, v16.16b \n"
"stp q0, q1, [%1], #32 \n" // store 8 ARGB pixels
"b.gt 1b \n"
: "+r"(src_ar30), // %0
"+r"(dst_argb), // %1
"+r"(width) // %2
:
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v16", "v17");
}
void AR30ToABGRRow_NEON(const uint8_t* src_ar30, uint8_t* dst_abgr, int width) {
asm volatile(
"movi v16.2d, #0x00ffff0000ffff00 \n"
"1: \n"
"ldp q0, q1, [%0], #32 \n" // load 8 AR30 pixels
"subs %w2, %w2, #8 \n" // 8 pixels per loop
"sri v0.4s, v0.4s, #2 \n"
"sri v1.4s, v1.4s, #2 \n"
"ushr v2.4s, v0.4s, #2 \n"
"ushr v3.4s, v1.4s, #2 \n"
"sli v2.4s, v0.4s, #16 \n"
"sli v3.4s, v1.4s, #16 \n"
"sri v0.4s, v0.4s, #4 \n"
"sri v1.4s, v1.4s, #4 \n"
"sri v0.4s, v0.4s, #16 \n"
"sri v1.4s, v1.4s, #16 \n"
"bit v0.16b, v2.16b, v16.16b \n"
"bit v1.16b, v3.16b, v16.16b \n"
"stp q0, q1, [%1], #32 \n" // store 8 ABGR pixels
"b.gt 1b \n"
: "+r"(src_ar30), // %0
"+r"(dst_abgr), // %1
"+r"(width) // %2
:
: "memory", "cc", "v0", "v1", "v2", "v3", "v16");
}
void AR30ToAB30Row_NEON(const uint8_t* src_ar30, uint8_t* dst_ab30, int width) {
asm volatile(
"movi v17.16b, #0xff \n"
"ushr v17.4s, v17.4s, #22 \n" // 0x000003ff
"shl v16.4s, v17.4s, #20 \n" // 0x3ff00000
"1: \n"
"ldp q0, q1, [%0], #32 \n" // load 8 AR30 pixels
"subs %w2, %w2, #8 \n" // 8 pixels per loop
"shl v2.4s, v0.4s, #20 \n"
"shl v3.4s, v1.4s, #20 \n"
"ushr v4.4s, v0.4s, #20 \n"
"ushr v5.4s, v1.4s, #20 \n"
"bit v0.16b, v2.16b, v16.16b \n"
"bit v1.16b, v3.16b, v16.16b \n"
"bit v0.16b, v4.16b, v17.16b \n"
"bit v1.16b, v5.16b, v17.16b \n"
"stp q0, q1, [%1], #32 \n" // store 8 AB30 pixels
"b.gt 1b \n"
: "+r"(src_ar30), // %0
"+r"(dst_ab30), // %1
"+r"(width) // %2
:
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v16", "v17");
}
void ARGBCopyAlphaRow_NEON(const uint8_t* src, uint8_t* dst, int width) {
asm volatile(
"movi v4.4s, #0xff, lsl #24 \n" // 0xff000000
"1: \n"
"ldp q0, q1, [%0], #32 \n" // load 8 src pixels
"ldp q2, q3, [%1] \n" // load 8 dst pixels
"subs %w2, %w2, #8 \n" // 8 pixels per loop
"bit v2.16b, v0.16b, v4.16b \n"
"bit v3.16b, v1.16b, v4.16b \n"
"stp q2, q3, [%1], #32 \n" // store 8 dst pixels
"b.gt 1b \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
:
: "memory", "cc", "v0", "v1", "v2", "v3", "v4");
}
void ARGBUnattenuateRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
int width) {
uint64_t tmp;
asm volatile(
"movi v16.4s, #0xff, lsl #24 \n" // 0xff000000
"1: \n"
"ldrb %w3, [%0, #3] \n"
"ldr s4, [%4, %w3, uxtw #2] \n"
"ldrb %w3, [%0, #7] \n"
"ldr s5, [%4, %w3, uxtw #2] \n"
"ldrb %w3, [%0, #11] \n"
"ldr s6, [%4, %w3, uxtw #2] \n"
"ldrb %w3, [%0, #15] \n"
"ldr s7, [%4, %w3, uxtw #2] \n"
"ldr q0, [%0], #16 \n"
"subs %w2, %w2, #4 \n"
"zip1 v1.16b, v0.16b, v0.16b \n"
"zip2 v2.16b, v0.16b, v0.16b \n"
"umull v3.4s, v1.4h, v4.h[0] \n"
"umull2 v5.4s, v1.8h, v5.h[0] \n"
"umull v6.4s, v2.4h, v6.h[0] \n"
"umull2 v7.4s, v2.8h, v7.h[0] \n"
"uzp2 v3.8h, v3.8h, v5.8h \n"
"uzp2 v6.8h, v6.8h, v7.8h \n"
"uqxtn v1.8b, v3.8h \n"
"uqxtn2 v1.16b, v6.8h \n"
"bit v1.16b, v0.16b, v16.16b \n"
"str q1, [%1], #16 \n"
"b.gt 1b \n"
: "+r"(src_argb), // %0
"+r"(dst_argb), // %1
"+r"(width), // %2
"=&r"(tmp) // %3
: "r"(fixed_invtbl8) // %4
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16");
}
void ARGBPolynomialRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
const float* poly,
int width) {
asm volatile(
"ldp q16, q17, [%3] \n" // c0, c1
"ldp q18, q19, [%3, #32] \n" // c2, c3
"subs %w2, %w2, #4 \n"
"b.lt 2f \n"
"1: \n"
"ldr q0, [%0], #16 \n" // load 4 pixels
"subs %w2, %w2, #4 \n"
"uxtl v1.8h, v0.8b \n"
"uxtl2 v3.8h, v0.16b \n"
"uxtl v0.4s, v1.4h \n"
"uxtl2 v1.4s, v1.8h \n"
"uxtl v2.4s, v3.4h \n"
"uxtl2 v3.4s, v3.8h \n"
"ucvtf v0.4s, v0.4s \n" // x0
"ucvtf v1.4s, v1.4s \n" // x1
"ucvtf v2.4s, v2.4s \n" // x2
"ucvtf v3.4s, v3.4s \n" // x3
"fmul v20.4s, v0.4s, v0.4s \n" // x0^2
"fmul v21.4s, v1.4s, v1.4s \n" // x1^2
"fmul v22.4s, v2.4s, v2.4s \n" // x2^2
"fmul v23.4s, v3.4s, v3.4s \n" // x3^2
"fmul v4.4s, v17.4s, v0.4s \n" // c1 * x0
"fmul v5.4s, v17.4s, v1.4s \n" // c1 * x1
"fmul v6.4s, v17.4s, v2.4s \n" // c1 * x2
"fmul v7.4s, v17.4s, v3.4s \n" // c1 * x3
"fmul v0.4s, v20.4s, v0.4s \n" // x0^3
"fmul v1.4s, v21.4s, v1.4s \n" // x1^3
"fmul v2.4s, v22.4s, v2.4s \n" // x2^3
"fmul v3.4s, v23.4s, v3.4s \n" // x3^3
"fadd v4.4s, v16.4s, v4.4s \n" // c0 + c1 * x0
"fadd v5.4s, v16.4s, v5.4s \n" // c0 + c1 * x1
"fadd v6.4s, v16.4s, v6.4s \n" // c0 + c1 * x2
"fadd v7.4s, v16.4s, v7.4s \n" // c0 + c1 * x3
"fmla v4.4s, v18.4s, v20.4s \n" // + c2 * x0^2
"fmla v5.4s, v18.4s, v21.4s \n" // + c2 * x1^2
"fmla v6.4s, v18.4s, v22.4s \n" // + c2 * x2^2
"fmla v7.4s, v18.4s, v23.4s \n" // + c2 * x3^2
"fmla v4.4s, v19.4s, v0.4s \n" // + c3 * x0^3
"fmla v5.4s, v19.4s, v1.4s \n" // + c3 * x1^3
"fmla v6.4s, v19.4s, v2.4s \n" // + c3 * x2^3
"fmla v7.4s, v19.4s, v3.4s \n" // + c3 * x3^3
"fcvtzs v4.4s, v4.4s \n"
"fcvtzs v5.4s, v5.4s \n"
"fcvtzs v6.4s, v6.4s \n"
"fcvtzs v7.4s, v7.4s \n"
"sqxtn v4.4h, v4.4s \n"
"sqxtn2 v4.8h, v5.4s \n"
"sqxtn v6.4h, v6.4s \n"
"sqxtn2 v6.8h, v7.4s \n"
"sqxtun v4.8b, v4.8h \n"
"sqxtun2 v4.16b, v6.8h \n"
"str q4, [%1], #16 \n"
"b.ge 1b \n"
"2: \n"
"adds %w2, %w2, #4 \n"
"b.eq 3f \n"
"ldr d0, [%0], #8 \n" // load 2 pixels
"uxtl v0.8h, v0.8b \n"
"uxtl v1.4s, v0.4h \n"
"uxtl2 v2.4s, v0.8h \n"
"ucvtf v1.4s, v1.4s \n" // x0
"ucvtf v2.4s, v2.4s \n" // x1
"fmul v5.4s, v1.4s, v1.4s \n" // x0^2
"fmul v6.4s, v2.4s, v2.4s \n" // x1^2
"fmul v3.4s, v17.4s, v1.4s \n" // c1 * x0
"fmul v4.4s, v17.4s, v2.4s \n" // c1 * x1
"fmul v1.4s, v5.4s, v1.4s \n" // x0^3
"fmul v2.4s, v6.4s, v2.4s \n" // x1^3
"fadd v3.4s, v16.4s, v3.4s \n" // c0 + c1 * x0
"fadd v4.4s, v16.4s, v4.4s \n" // c0 + c1 * x1
"fmla v3.4s, v18.4s, v5.4s \n" // + c2 * x0^2
"fmla v4.4s, v18.4s, v6.4s \n" // + c2 * x1^2
"fmla v3.4s, v19.4s, v1.4s \n" // + c3 * x0^3
"fmla v4.4s, v19.4s, v2.4s \n" // + c3 * x1^3
"fcvtzs v3.4s, v3.4s \n"
"fcvtzs v4.4s, v4.4s \n"
"sqxtn v3.4h, v3.4s \n"
"sqxtn2 v3.8h, v4.4s \n"
"sqxtun v3.8b, v3.8h \n"
"str d3, [%1], #8 \n"
"3: \n"
: "+r"(src_argb), // %0
"+r"(dst_argb), // %1
"+r"(width) // %2
: "r"(poly) // %3
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16",
"v17", "v18", "v19", "v20", "v21", "v22", "v23");
}
void ARGBColorTableRow_NEON(uint8_t* dst_argb,
const uint8_t* table_argb,
int width) {
uint64_t b, g, r, a;
asm volatile(
"1: \n"
"ldrb %w2, [%0] \n"
"ldrb %w3, [%0, #1] \n"
"ldrb %w4, [%0, #2] \n"
"ldrb %w5, [%0, #3] \n"
"subs %w1, %w1, #1 \n"
"ldr %w2, [%6, %w2, uxtw #2] \n"
"ldr %w3, [%6, %w3, uxtw #2] \n"
"ldr %w4, [%6, %w4, uxtw #2] \n"
"ldr %w5, [%6, %w5, uxtw #2] \n"
"bfi %w3, %w2, #0, #8 \n"
"lsr %w4, %w4, #16 \n"
"lsr %w5, %w5, #24 \n"
"strh %w3, [%0] \n"
"strb %w4, [%0, #2] \n"
"strb %w5, [%0, #3] \n"
"add %0, %0, #4 \n"
"b.gt 1b \n"
: "+r"(dst_argb), // %0
"+r"(width), // %1
"=&r"(b), // %2
"=&r"(g), // %3
"=&r"(r), // %4
"=&r"(a) // %5
: "r"(table_argb) // %6
: "memory", "cc");
}
void RGBColorTableRow_NEON(uint8_t* dst_argb,
const uint8_t* table_argb,
int width) {
uint64_t b, g, r;
asm volatile(
"1: \n"
"ldrb %w2, [%0] \n"
"ldrb %w3, [%0, #1] \n"
"ldrb %w4, [%0, #2] \n"
"subs %w1, %w1, #1 \n"
"ldr %w2, [%5, %w2, uxtw #2] \n"
"ldr %w3, [%5, %w3, uxtw #2] \n"
"ldr %w4, [%5, %w4, uxtw #2] \n"
"bfi %w3, %w2, #0, #8 \n"
"lsr %w4, %w4, #16 \n"
"strh %w3, [%0] \n"
"strb %w4, [%0, #2] \n"
"add %0, %0, #4 \n"
"b.gt 1b \n"
: "+r"(dst_argb), // %0
"+r"(width), // %1
"=&r"(b), // %2
"=&r"(g), // %3
"=&r"(r) // %4
: "r"(table_argb) // %5
: "memory", "cc");
}
static const uvec8 kLumaTblIdx = {1, 1, 1, 1, 3, 3, 3, 3,
5, 5, 5, 5, 7, 7, 7, 7};
void ARGBLumaColorTableRow_NEON(const uint8_t* src_argb,
uint8_t* dst_argb,
int width,
const uint8_t* luma,
uint32_t lumacoeff) {
uint64_t p0, p1, t0, t1;
asm volatile(
"dup v4.4s, %w8 \n" // broadcast 4 byte coeffs
"ldr q5, [%9] \n"
"movi v6.4s, #0xff, lsl #24 \n"
"1: \n"
"ldr q0, [%0], #16 \n" // load 4 ARGB pixels
"subs %w2, %w2, #4 \n" // 4 pixels per loop
"umull v1.8h, v0.8b, v4.8b \n"
"umull2 v2.8h, v0.16b, v4.16b \n"
"addp v1.8h, v1.8h, v2.8h \n"
"addp v1.8h, v1.8h, v1.8h \n"
"bic v1.8h, #0x80, lsl #8 \n" // clear bit 15
"tbl v1.16b, {v1.16b}, v5.16b \n"
"zip2 v2.16b, v0.16b, v1.16b \n" // offsets pixels 2, 3
"zip1 v1.16b, v0.16b, v1.16b \n" // offsets pixels 0, 1
"umov %3, v1.d[0] \n"
"umov %4, v1.d[1] \n"
"add %5, %7, %w3, uxth \n"
"ubfx %6, %3, #16, #16 \n"
"ldr b3, [%5] \n"
"add %6, %7, %6 \n"
"ubfx %5, %3, #32, #16 \n"
"ld1 {v3.b}[1], [%6] \n"
"add %5, %7, %5 \n"
"add %6, %7, %w4, uxth \n"
"ld1 {v3.b}[2], [%5] \n"
"ld1 {v3.b}[4], [%6] \n"
"ubfx %5, %4, #16, #16 \n"
"ubfx %6, %4, #32, #16 \n"
"add %5, %7, %5 \n"
"add %6, %7, %6 \n"
"ld1 {v3.b}[5], [%5] \n"
"ld1 {v3.b}[6], [%6] \n"
"umov %3, v2.d[0] \n"
"umov %4, v2.d[1] \n"
"add %5, %7, %w3, uxth \n"
"ubfx %6, %3, #16, #16 \n"
"ld1 {v3.b}[8], [%5] \n"
"add %6, %7, %6 \n"
"ubfx %5, %3, #32, #16 \n"
"ld1 {v3.b}[9], [%6] \n"
"add %5, %7, %5 \n"
"add %6, %7, %w4, uxth \n"
"ld1 {v3.b}[10], [%5] \n"
"ld1 {v3.b}[12], [%6] \n"
"ubfx %5, %4, #16, #16 \n"
"ubfx %6, %4, #32, #16 \n"
"add %5, %7, %5 \n"
"add %6, %7, %6 \n"
"ld1 {v3.b}[13], [%5] \n"
"ld1 {v3.b}[14], [%6] \n"
"bit v3.16b, v0.16b, v6.16b \n"
"str q3, [%1], #16 \n"
"b.gt 1b \n"
: "+r"(src_argb), // %0
"+r"(dst_argb), // %1
"+r"(width), // %2
"=&r"(p0), // %3
"=&r"(p1), // %4
"=&r"(t0), // %5
"=&r"(t1) // %6
: "r"(luma), // %7
"r"(lumacoeff), // %8
"r"(&kLumaTblIdx) // %9
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6");
}
void ARGBAffineRow_NEON(const uint8_t* src_argb,
int src_argb_stride,
uint8_t* dst_argb,
const float* uv_dudv,
int width) {
int64_t off0, off1;
asm volatile(
"ld1r {v2.2d}, [%2], #8 \n" // [u, v, u, v]
"ld1r {v6.2d}, [%2] \n" // [du, dv, du, dv]
"dup v5.2s, %w5 \n" // [stride, stride]
"movi v4.2s, #4 \n" // [4, 4]
"zip1 v5.4s, v4.4s, v5.4s \n" // [4, stride, 4, stride]
"subs %w1, %w1, #4 \n"
"b.lt 2f \n"
"fadd v4.4s, v6.4s, v6.4s \n" // 2 * [du, dv, du, dv]
"fadd v3.2s, v2.2s, v6.2s \n" // [u+du, v+dv]
"ins v2.d[1], v3.d[0] \n" // [u, v, u+du, v+dv]
"fadd v3.4s, v2.4s, v4.4s \n" // [u+2du, v+2dv, u+3du,
// v+3dv]
"fadd v4.4s, v4.4s, v4.4s \n" // 4 * [du, dv, du, dv]
"1: \n"
"fcvtzs v0.4s, v2.4s \n"
"fcvtzs v1.4s, v3.4s \n"
"fadd v2.4s, v2.4s, v4.4s \n"
"fadd v3.4s, v3.4s, v4.4s \n"
"mul v0.4s, v0.4s, v5.4s \n"
"mul v1.4s, v1.4s, v5.4s \n"
"addp v7.4s, v0.4s, v1.4s \n"
"smov %3, v7.s[0] \n"
"smov %4, v7.s[1] \n"
"ldr %w3, [%6, %3] \n"
"ldr %w4, [%6, %4] \n"
"stp %w3, %w4, [%0], #8 \n"
"smov %3, v7.s[2] \n"
"smov %4, v7.s[3] \n"
"ldr %w3, [%6, %3] \n"
"ldr %w4, [%6, %4] \n"
"stp %w3, %w4, [%0], #8 \n"
"subs %w1, %w1, #4 \n"
"b.ge 1b \n"
"2: \n"
"adds %w1, %w1, #4 \n"
"b.eq 4f \n"
"3: \n"
"fcvtzs v0.2s, v2.2s \n"
"fadd v2.2s, v2.2s, v6.2s \n"
"mul v0.2s, v0.2s, v5.2s \n"
"addp v0.2s, v0.2s, v0.2s \n"
"smov %3, v0.s[0] \n"
"ldr %w3, [%6, %3] \n"
"str %w3, [%0], #4 \n"
"subs %w1, %w1, #1 \n"
"b.gt 3b \n"
"4: \n"
: "+r"(dst_argb), // %0
"+r"(width), // %1
"+r"(uv_dudv), // %2
"=&r"(off0), // %3
"=&r"(off1) // %4
: "r"(src_argb_stride), // %5
"r"(src_argb) // %6
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7");
}
#endif // !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) #endif // !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1574,6 +1574,20 @@ TEST_F(LibYUVPlanarTest, TestAffine) {
} }
} }
#endif #endif
#if defined(HAS_ARGBAFFINEROW_NEON)
SIMD_ALIGNED(uint8_t interpolate_pixels_Opt[1280][4]);
ARGBAffineRow_NEON(&orig_pixels_0[0][0], 0, &interpolate_pixels_Opt[0][0],
uv_step, 1280);
ASSERT_EQ(0, memcmp(interpolate_pixels_Opt, interpolate_pixels_C, 1280 * 4));
int has_neon = TestCpuFlag(kCpuHasNEON);
if (has_neon) {
for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
ARGBAffineRow_NEON(&orig_pixels_0[0][0], 0, &interpolate_pixels_Opt[0][0],
uv_step, 1280);
}
}
#endif
} }
#endif // ENABLE_ROW_TESTS #endif // ENABLE_ROW_TESTS
@ -2417,7 +2431,7 @@ TEST_F(LibYUVPlanarTest, DISABLED_ARM(ARGBBlurSmall_Opt)) {
ASSERT_LE(max_diff, 1); ASSERT_LE(max_diff, 1);
} }
TEST_F(LibYUVPlanarTest, DISABLED_ARM(TestARGBPolynomial)) { TEST_F(LibYUVPlanarTest, TestARGBPolynomial) {
SIMD_ALIGNED(uint8_t orig_pixels[1280][4]); SIMD_ALIGNED(uint8_t orig_pixels[1280][4]);
SIMD_ALIGNED(uint8_t dst_pixels_opt[1280][4]); SIMD_ALIGNED(uint8_t dst_pixels_opt[1280][4]);
SIMD_ALIGNED(uint8_t dst_pixels_c[1280][4]); SIMD_ALIGNED(uint8_t dst_pixels_c[1280][4]);