libyuv/source/row_any.cc
Frank Barchard d5b76112f8 [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%).

ARM64 (Apple M6) Benchmark (1280 width, 10000 iterations):
----------------------------------------------------------------
Function                 Before C (ms) After NEON (ms)  Improvement
----------------------------------------------------------------
AR30ToAB30Row                    1.20           0.70        1.72x
AR30ToABGRRow                    1.88           1.03        1.83x
AR30ToARGBRow                    1.88           0.87        2.17x
ARGBAffineRow                    7.96           2.31        3.44x
ARGBColorTableRow                8.17           7.43        1.10x
ARGBCopyAlphaRow                 1.37           0.53        2.58x
ARGBLumaColorTableRow            8.18           5.24        1.56x
ARGBPolynomialRow                8.73           7.55        1.16x
ARGBUnattenuateRow               6.00           2.05        2.93x
CopyRow_16                       0.18           0.18        1.00x
MirrorRow_16                     0.34           0.20        1.73x
RGBColorTableRow                 6.15           5.58        1.10x
----------------------------------------------------------------

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
2026-10-27 14:38:21 -07:00

2978 lines
125 KiB
C++

/*
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "libyuv/row.h"
#include <assert.h>
#include <string.h> // For memset.
#ifdef __cplusplus
namespace libyuv {
extern "C" {
#endif
// Subsampled source needs to be increase by 1 if not even.
#define SS(width, shift) (((width) + (1 << (shift)) - 1) >> (shift))
#ifdef LIBYUV_MSAN
#define MSAN_MEMSET(a, b, c) memset(a, b, c)
#else
#define MSAN_MEMSET(a, b, c)
#endif
// Any 4 planes to 1
#define ANY41(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* y_buf, const uint8_t* u_buf, \
const uint8_t* v_buf, const uint8_t* a_buf, uint8_t* dst_ptr, \
int width) { \
SIMD_ALIGNED(uint8_t vin[64 * 4]); \
static_assert(MASK + 1 <= sizeof(vin) / 4, "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert(SS(MASK + 1, DUVSHIFT) * 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(y_buf, u_buf, v_buf, a_buf, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r); \
memcpy(vin + 64, u_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
memcpy(vin + 128, v_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
memcpy(vin + 192, a_buf + np, r); \
ANY_SIMD(vin, vin + 64, vin + 128, vin + 192, vout, MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
#ifdef HAS_MERGEARGBROW_SSE2
ANY41(MergeARGBRow_Any_SSE2, MergeARGBRow_SSE2, 0, 0, 4, 7)
#endif
#ifdef HAS_MERGEARGBROW_AVX2
ANY41(MergeARGBRow_Any_AVX2, MergeARGBRow_AVX2, 0, 0, 4, 15)
#endif
#ifdef HAS_MERGEARGBROW_NEON
ANY41(MergeARGBRow_Any_NEON, MergeARGBRow_NEON, 0, 0, 4, 15)
#endif
// Note that odd width replication includes 444 due to implementation
// on arm that subsamples 444 to 422 internally.
// Any 4 planes to 1 with yuvconstants
#define ANY41C(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* y_buf, const uint8_t* u_buf, \
const uint8_t* v_buf, const uint8_t* a_buf, uint8_t* dst_ptr, \
const struct YuvConstants* yuvconstants, int width) { \
SIMD_ALIGNED(uint8_t vin[64 * 4]); \
static_assert(MASK + 1 <= sizeof(vin) / 4, "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert(SS(MASK + 1, DUVSHIFT) * 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(y_buf, u_buf, v_buf, a_buf, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r); \
memcpy(vin + 64, u_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
memcpy(vin + 128, v_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
memcpy(vin + 192, a_buf + np, r); \
if (width & 1) { \
vin[64 + SS(r, UVSHIFT)] = vin[64 + SS(r, UVSHIFT) - 1]; \
vin[128 + SS(r, UVSHIFT)] = vin[128 + SS(r, UVSHIFT) - 1]; \
} \
ANY_SIMD(vin, vin + 64, vin + 128, vin + 192, vout, yuvconstants, \
MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
#ifdef HAS_I444ALPHATOARGBROW_SSSE3
ANY41C(I444AlphaToARGBRow_Any_SSSE3, I444AlphaToARGBRow_SSSE3, 0, 0, 4, 7)
#endif
#ifdef HAS_I444ALPHATOARGBROW_AVX2
ANY41C(I444AlphaToARGBRow_Any_AVX2, I444AlphaToARGBRow_AVX2, 0, 0, 4, 15)
#endif
#ifdef HAS_I422ALPHATOARGBROW_SSSE3
ANY41C(I422AlphaToARGBRow_Any_SSSE3, I422AlphaToARGBRow_SSSE3, 1, 0, 4, 7)
#endif
#ifdef HAS_I422ALPHATOARGBROW_AVX2
ANY41C(I422AlphaToARGBRow_Any_AVX2, I422AlphaToARGBRow_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_I444ALPHATOARGBROW_NEON
ANY41C(I444AlphaToARGBRow_Any_NEON, I444AlphaToARGBRow_NEON, 0, 0, 4, 7)
#endif
#ifdef HAS_I422ALPHATOARGBROW_NEON
ANY41C(I422AlphaToARGBRow_Any_NEON, I422AlphaToARGBRow_NEON, 1, 0, 4, 7)
#endif
#ifdef HAS_I422ALPHATOARGBROW_LSX
ANY41C(I422AlphaToARGBRow_Any_LSX, I422AlphaToARGBRow_LSX, 1, 0, 4, 7)
#endif
#ifdef HAS_I422ALPHATOARGBROW_LASX
ANY41C(I422AlphaToARGBRow_Any_LASX, I422AlphaToARGBRow_LASX, 1, 0, 4, 15)
#endif
#undef ANY41C
// Any 4 planes to 1 plane of 8 bit with yuvconstants
#define ANY41CT(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, T, SBPP, BPP, MASK) \
void NAMEANY(const T* y_buf, const T* u_buf, const T* v_buf, const T* a_buf, \
uint8_t* dst_ptr, const struct YuvConstants* yuvconstants, \
int width) { \
SIMD_ALIGNED(T vin[16 * 4]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin) / 4, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert(SS(MASK + 1, DUVSHIFT) * BPP <= sizeof(vout), \
"vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(y_buf, u_buf, v_buf, a_buf, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r * SBPP); \
memcpy(vin + 16, u_buf + (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP); \
memcpy(vin + 32, v_buf + (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP); \
memcpy(vin + 48, a_buf + np, r * SBPP); \
ANY_SIMD(vin, vin + 16, vin + 32, vin + 48, vout, yuvconstants, MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
#ifdef HAS_I210ALPHATOARGBROW_NEON
ANY41CT(I210AlphaToARGBRow_Any_NEON,
I210AlphaToARGBRow_NEON,
1,
0,
uint16_t,
2,
4,
7)
#endif
#ifdef HAS_I410ALPHATOARGBROW_NEON
ANY41CT(I410AlphaToARGBRow_Any_NEON,
I410AlphaToARGBRow_NEON,
0,
0,
uint16_t,
2,
4,
7)
#endif
#ifdef HAS_I210ALPHATOARGBROW_SSSE3
ANY41CT(I210AlphaToARGBRow_Any_SSSE3,
I210AlphaToARGBRow_SSSE3,
1,
0,
uint16_t,
2,
4,
7)
#endif
#ifdef HAS_I210ALPHATOARGBROW_AVX2
ANY41CT(I210AlphaToARGBRow_Any_AVX2,
I210AlphaToARGBRow_AVX2,
1,
0,
uint16_t,
2,
4,
15)
#endif
#ifdef HAS_I410ALPHATOARGBROW_SSSE3
ANY41CT(I410AlphaToARGBRow_Any_SSSE3,
I410AlphaToARGBRow_SSSE3,
0,
0,
uint16_t,
2,
4,
7)
#endif
#ifdef HAS_I410ALPHATOARGBROW_AVX2
ANY41CT(I410AlphaToARGBRow_Any_AVX2,
I410AlphaToARGBRow_AVX2,
0,
0,
uint16_t,
2,
4,
15)
#endif
#undef ANY41CT
// Any 4 planes to 1 plane with parameter
#define ANY41PT(NAMEANY, ANY_SIMD, STYPE, SBPP, DTYPE, BPP, MASK) \
void NAMEANY(const STYPE* r_buf, const STYPE* g_buf, const STYPE* b_buf, \
const STYPE* a_buf, DTYPE* dst_ptr, int depth, int width) { \
SIMD_ALIGNED(STYPE vin[16 * 4]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin) / 4, \
"vin buffer too small"); \
SIMD_ALIGNED(DTYPE 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(r_buf, g_buf, b_buf, a_buf, dst_ptr, depth, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, r_buf + np, r * SBPP); \
memcpy(vin + 16, g_buf + np, r * SBPP); \
memcpy(vin + 32, b_buf + np, r * SBPP); \
memcpy(vin + 48, a_buf + np, r * SBPP); \
ANY_SIMD(vin, vin + 16, vin + 32, vin + 48, vout, depth, MASK + 1); \
memcpy((uint8_t*)dst_ptr + np * BPP, vout, r * BPP); \
}
#ifdef HAS_MERGEAR64ROW_AVX2
ANY41PT(MergeAR64Row_Any_AVX2, MergeAR64Row_AVX2, uint16_t, 2, uint16_t, 8, 15)
#endif
#ifdef HAS_MERGEAR64ROW_NEON
ANY41PT(MergeAR64Row_Any_NEON, MergeAR64Row_NEON, uint16_t, 2, uint16_t, 8, 7)
#endif
#ifdef HAS_MERGEARGB16TO8ROW_AVX2
ANY41PT(MergeARGB16To8Row_Any_AVX2,
MergeARGB16To8Row_AVX2,
uint16_t,
2,
uint8_t,
4,
15)
#endif
#ifdef HAS_MERGEARGB16TO8ROW_NEON
ANY41PT(MergeARGB16To8Row_Any_NEON,
MergeARGB16To8Row_NEON,
uint16_t,
2,
uint8_t,
4,
7)
#endif
#undef ANY41PT
// Any 3 planes to 1.
#define ANY31(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* y_buf, const uint8_t* u_buf, \
const uint8_t* v_buf, uint8_t* dst_ptr, int width) { \
SIMD_ALIGNED(uint8_t vin[64 * 3]); \
static_assert(MASK + 1 <= sizeof(vin) / 3, "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert(SS(MASK + 1, DUVSHIFT) * BPP <= sizeof(vout), \
"vout buffer too small"); \
memset(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(y_buf, u_buf, v_buf, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r); \
memcpy(vin + 64, u_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
memcpy(vin + 128, v_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
ANY_SIMD(vin, vin + 64, vin + 128, vout, MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
// Merge functions.
#ifdef HAS_MERGERGBROW_SSSE3
ANY31(MergeRGBRow_Any_SSSE3, MergeRGBRow_SSSE3, 0, 0, 3, 15)
#endif
#ifdef HAS_MERGERGBROW_NEON
ANY31(MergeRGBRow_Any_NEON, MergeRGBRow_NEON, 0, 0, 3, 15)
#endif
#ifdef HAS_MERGEXRGBROW_SSE2
ANY31(MergeXRGBRow_Any_SSE2, MergeXRGBRow_SSE2, 0, 0, 4, 7)
#endif
#ifdef HAS_MERGEXRGBROW_AVX2
ANY31(MergeXRGBRow_Any_AVX2, MergeXRGBRow_AVX2, 0, 0, 4, 15)
#endif
#ifdef HAS_MERGEXRGBROW_NEON
ANY31(MergeXRGBRow_Any_NEON, MergeXRGBRow_NEON, 0, 0, 4, 15)
#endif
#ifdef HAS_I422TOYUY2ROW_SSE2
ANY31(I422ToYUY2Row_Any_SSE2, I422ToYUY2Row_SSE2, 1, 1, 4, 15)
ANY31(I422ToUYVYRow_Any_SSE2, I422ToUYVYRow_SSE2, 1, 1, 4, 15)
#endif
#ifdef HAS_I422TOYUY2ROW_AVX2
ANY31(I422ToYUY2Row_Any_AVX2, I422ToYUY2Row_AVX2, 1, 1, 4, 31)
ANY31(I422ToUYVYRow_Any_AVX2, I422ToUYVYRow_AVX2, 1, 1, 4, 31)
#endif
#ifdef HAS_I422TOYUY2ROW_NEON
ANY31(I422ToYUY2Row_Any_NEON, I422ToYUY2Row_NEON, 1, 1, 4, 15)
#endif
#ifdef HAS_I422TOYUY2ROW_LSX
ANY31(I422ToYUY2Row_Any_LSX, I422ToYUY2Row_LSX, 1, 1, 4, 15)
#endif
#ifdef HAS_I422TOYUY2ROW_LASX
ANY31(I422ToYUY2Row_Any_LASX, I422ToYUY2Row_LASX, 1, 1, 4, 31)
#endif
#ifdef HAS_I422TOUYVYROW_NEON
ANY31(I422ToUYVYRow_Any_NEON, I422ToUYVYRow_NEON, 1, 1, 4, 15)
#endif
#ifdef HAS_I422TOUYVYROW_LSX
ANY31(I422ToUYVYRow_Any_LSX, I422ToUYVYRow_LSX, 1, 1, 4, 15)
#endif
#ifdef HAS_I422TOUYVYROW_LASX
ANY31(I422ToUYVYRow_Any_LASX, I422ToUYVYRow_LASX, 1, 1, 4, 31)
#endif
#ifdef HAS_BLENDPLANEROW_AVX2
ANY31(BlendPlaneRow_Any_AVX2, BlendPlaneRow_AVX2, 0, 0, 1, 31)
#endif
#ifdef HAS_BLENDPLANEROW_SSSE3
ANY31(BlendPlaneRow_Any_SSSE3, BlendPlaneRow_SSSE3, 0, 0, 1, 7)
#endif
#ifdef HAS_BLENDPLANEROW_NEON
ANY31(BlendPlaneRow_Any_NEON, BlendPlaneRow_NEON, 0, 0, 1, 15)
#endif
#ifdef HAS_BLENDPLANEROW_WASMSIMD
ANY31(BlendPlaneRow_Any_WASMSIMD, BlendPlaneRow_WASMSIMD, 0, 0, 1, 15)
#endif
#undef ANY31
// Note that odd width replication includes 444 due to implementation
// on arm that subsamples 444 to 422 internally.
// Any 3 planes to 1 with yuvconstants
#define ANY31C(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* y_buf, const uint8_t* u_buf, \
const uint8_t* v_buf, uint8_t* dst_ptr, \
const struct YuvConstants* yuvconstants, int width) { \
SIMD_ALIGNED(uint8_t vin[128 * 3]); \
static_assert(MASK + 1 <= sizeof(vin) / 3, "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[128]); \
static_assert(SS(MASK + 1, DUVSHIFT) * BPP <= sizeof(vout), \
"vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(y_buf, u_buf, v_buf, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r); \
memcpy(vin + 128, u_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
memcpy(vin + 256, v_buf + (np >> UVSHIFT), SS(r, UVSHIFT)); \
if (width & 1) { \
vin[128 + SS(r, UVSHIFT)] = vin[128 + SS(r, UVSHIFT) - 1]; \
vin[256 + SS(r, UVSHIFT)] = vin[256 + SS(r, UVSHIFT) - 1]; \
} \
ANY_SIMD(vin, vin + 128, vin + 256, vout, yuvconstants, MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
#ifdef HAS_I422TOARGBROW_SSSE3
ANY31C(I422ToARGBRow_Any_SSSE3, I422ToARGBRow_SSSE3, 1, 0, 4, 7)
#endif
#ifdef HAS_I422TORGBAROW_SSSE3
ANY31C(I422ToRGBARow_Any_SSSE3, I422ToRGBARow_SSSE3, 1, 0, 4, 7)
#endif
#ifdef HAS_I422TOARGB4444ROW_SSSE3
ANY31C(I422ToARGB4444Row_Any_SSSE3, I422ToARGB4444Row_SSSE3, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TOARGB1555ROW_SSSE3
ANY31C(I422ToARGB1555Row_Any_SSSE3, I422ToARGB1555Row_SSSE3, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TORGB565ROW_SSSE3
ANY31C(I422ToRGB565Row_Any_SSSE3, I422ToRGB565Row_SSSE3, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TORGB24ROW_SSSE3
ANY31C(I422ToRGB24Row_Any_SSSE3, I422ToRGB24Row_SSSE3, 1, 0, 3, 15)
#endif
#ifdef HAS_I422TOAR30ROW_SSSE3
ANY31C(I422ToAR30Row_Any_SSSE3, I422ToAR30Row_SSSE3, 1, 0, 4, 7)
#endif
#ifdef HAS_I422TOAR30ROW_AVX2
ANY31C(I422ToAR30Row_Any_AVX2, I422ToAR30Row_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_I444TOARGBROW_SSSE3
ANY31C(I444ToARGBRow_Any_SSSE3, I444ToARGBRow_SSSE3, 0, 0, 4, 7)
#endif
#ifdef HAS_I444TORGB24ROW_SSSE3
ANY31C(I444ToRGB24Row_Any_SSSE3, I444ToRGB24Row_SSSE3, 0, 0, 3, 15)
#endif
#ifdef HAS_I422TORGB24ROW_AVX2
ANY31C(I422ToRGB24Row_Any_AVX2, I422ToRGB24Row_AVX2, 1, 0, 3, 15)
#endif
#ifdef HAS_I422TOARGBROW_AVX2
ANY31C(I422ToARGBRow_Any_AVX2, I422ToARGBRow_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_I422TORGBAROW_AVX2
ANY31C(I422ToRGBARow_Any_AVX2, I422ToRGBARow_AVX2, 1, 0, 4, 15)
#endif
#ifdef HAS_I444TOARGBROW_AVX2
ANY31C(I444ToARGBRow_Any_AVX2, I444ToARGBRow_AVX2, 0, 0, 4, 15)
#endif
#ifdef HAS_I444TORGB24ROW_AVX2
ANY31C(I444ToRGB24Row_Any_AVX2, I444ToRGB24Row_AVX2, 0, 0, 3, 31)
#endif
#ifdef HAS_I422TOARGB4444ROW_AVX2
ANY31C(I422ToARGB4444Row_Any_AVX2, I422ToARGB4444Row_AVX2, 1, 0, 2, 15)
#endif
#ifdef HAS_I422TOARGB1555ROW_AVX2
ANY31C(I422ToARGB1555Row_Any_AVX2, I422ToARGB1555Row_AVX2, 1, 0, 2, 15)
#endif
#ifdef HAS_I422TORGB565ROW_AVX2
ANY31C(I422ToRGB565Row_Any_AVX2, I422ToRGB565Row_AVX2, 1, 0, 2, 15)
#endif
#ifdef HAS_I444TORGB24ROW_NEON
ANY31C(I444ToRGB24Row_Any_NEON, I444ToRGB24Row_NEON, 0, 0, 3, 7)
#endif
#ifdef HAS_I422TOAR30ROW_NEON
ANY31C(I422ToAR30Row_Any_NEON, I422ToAR30Row_NEON, 1, 0, 4, 7)
#endif
#ifdef HAS_I422TOARGBROW_NEON
ANY31C(I444ToARGBRow_Any_NEON, I444ToARGBRow_NEON, 0, 0, 4, 7)
ANY31C(I422ToARGBRow_Any_NEON, I422ToARGBRow_NEON, 1, 0, 4, 7)
ANY31C(I422ToRGBARow_Any_NEON, I422ToRGBARow_NEON, 1, 0, 4, 7)
ANY31C(I422ToRGB24Row_Any_NEON, I422ToRGB24Row_NEON, 1, 0, 3, 7)
ANY31C(I422ToARGB4444Row_Any_NEON, I422ToARGB4444Row_NEON, 1, 0, 2, 7)
ANY31C(I422ToARGB1555Row_Any_NEON, I422ToARGB1555Row_NEON, 1, 0, 2, 7)
ANY31C(I422ToRGB565Row_Any_NEON, I422ToRGB565Row_NEON, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TOARGBROW_LSX
ANY31C(I422ToARGBRow_Any_LSX, I422ToARGBRow_LSX, 1, 0, 4, 7)
ANY31C(I422ToRGBARow_Any_LSX, I422ToRGBARow_LSX, 1, 0, 4, 7)
ANY31C(I422ToRGB24Row_Any_LSX, I422ToRGB24Row_LSX, 1, 0, 3, 7)
ANY31C(I422ToRGB565Row_Any_LSX, I422ToRGB565Row_LSX, 1, 0, 2, 7)
ANY31C(I422ToARGB4444Row_Any_LSX, I422ToARGB4444Row_LSX, 1, 0, 2, 7)
ANY31C(I422ToARGB1555Row_Any_LSX, I422ToARGB1555Row_LSX, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TOARGBROW_LASX
ANY31C(I422ToARGBRow_Any_LASX, I422ToARGBRow_LASX, 1, 0, 4, 15)
ANY31C(I422ToRGBARow_Any_LASX, I422ToRGBARow_LASX, 1, 0, 4, 15)
ANY31C(I422ToRGB24Row_Any_LASX, I422ToRGB24Row_LASX, 1, 0, 3, 15)
ANY31C(I422ToRGB565Row_Any_LASX, I422ToRGB565Row_LASX, 1, 0, 2, 15)
ANY31C(I422ToARGB4444Row_Any_LASX, I422ToARGB4444Row_LASX, 1, 0, 2, 15)
ANY31C(I422ToARGB1555Row_Any_LASX, I422ToARGB1555Row_LASX, 1, 0, 2, 15)
#endif
#ifdef HAS_I444TOARGBROW_LSX
ANY31C(I444ToARGBRow_Any_LSX, I444ToARGBRow_LSX, 0, 0, 4, 7)
#endif
#ifdef HAS_I444TOARGBROW_LASX
ANY31C(I444ToARGBRow_Any_LASX, I444ToARGBRow_LASX, 0, 0, 4, 15)
#endif
#ifdef HAS_I422TOARGBROW_WASMSIMD
ANY31C(I422ToARGBRow_Any_WASMSIMD, I422ToARGBRow_WASMSIMD, 1, 0, 4, 7)
#endif
#ifdef HAS_I422TOAR30ROW_WASMSIMD
ANY31C(I422ToAR30Row_Any_WASMSIMD, I422ToAR30Row_WASMSIMD, 1, 0, 4, 7)
#endif
#ifdef HAS_I422TORGB24ROW_WASMSIMD
ANY31C(I422ToRGB24Row_Any_WASMSIMD, I422ToRGB24Row_WASMSIMD, 1, 0, 3, 15)
#endif
#ifdef HAS_I422TORGB565ROW_WASMSIMD
ANY31C(I422ToRGB565Row_Any_WASMSIMD, I422ToRGB565Row_WASMSIMD, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TOARGB1555ROW_WASMSIMD
ANY31C(I422ToARGB1555Row_Any_WASMSIMD, I422ToARGB1555Row_WASMSIMD, 1, 0, 2, 7)
#endif
#ifdef HAS_I422TOARGB4444ROW_WASMSIMD
ANY31C(I422ToARGB4444Row_Any_WASMSIMD, I422ToARGB4444Row_WASMSIMD, 1, 0, 2, 7)
#endif
#undef ANY31C
// Any 3 planes of 16 bit to 1 with yuvconstants
// TODO(fbarchard): consider sharing this code with ANY31C
#define ANY31CT(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, T, SBPP, BPP, MASK) \
void NAMEANY(const T* y_buf, const T* u_buf, const T* v_buf, \
uint8_t* dst_ptr, const struct YuvConstants* yuvconstants, \
int width) { \
SIMD_ALIGNED(T vin[16 * 3]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin) / 3, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert(SS(MASK + 1, DUVSHIFT) * BPP <= sizeof(vout), \
"vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(y_buf, u_buf, v_buf, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r * SBPP); \
memcpy(vin + 16, u_buf + (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP); \
memcpy(vin + 32, v_buf + (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP); \
ANY_SIMD(vin, vin + 16, vin + 32, vout, yuvconstants, MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
#ifdef HAS_I210TOAR30ROW_SSSE3
ANY31CT(I210ToAR30Row_Any_SSSE3, I210ToAR30Row_SSSE3, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I210TOARGBROW_SSSE3
ANY31CT(I210ToARGBRow_Any_SSSE3, I210ToARGBRow_SSSE3, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I210TOARGBROW_AVX2
ANY31CT(I210ToARGBRow_Any_AVX2, I210ToARGBRow_AVX2, 1, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_I210TOAR30ROW_AVX2
ANY31CT(I210ToAR30Row_Any_AVX2, I210ToAR30Row_AVX2, 1, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_I410TOAR30ROW_SSSE3
ANY31CT(I410ToAR30Row_Any_SSSE3, I410ToAR30Row_SSSE3, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I410TOARGBROW_SSSE3
ANY31CT(I410ToARGBRow_Any_SSSE3, I410ToARGBRow_SSSE3, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I410TOARGBROW_AVX2
ANY31CT(I410ToARGBRow_Any_AVX2, I410ToARGBRow_AVX2, 0, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_I410TOAR30ROW_AVX2
ANY31CT(I410ToAR30Row_Any_AVX2, I410ToAR30Row_AVX2, 0, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_I212TOAR30ROW_SSSE3
ANY31CT(I212ToAR30Row_Any_SSSE3, I212ToAR30Row_SSSE3, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I212TOARGBROW_SSSE3
ANY31CT(I212ToARGBRow_Any_SSSE3, I212ToARGBRow_SSSE3, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I212TOARGBROW_AVX2
ANY31CT(I212ToARGBRow_Any_AVX2, I212ToARGBRow_AVX2, 1, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_I212TOAR30ROW_AVX2
ANY31CT(I212ToAR30Row_Any_AVX2, I212ToAR30Row_AVX2, 1, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_I210TOARGBROW_NEON
ANY31CT(I210ToARGBRow_Any_NEON, I210ToARGBRow_NEON, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I410TOARGBROW_NEON
ANY31CT(I410ToARGBRow_Any_NEON, I410ToARGBRow_NEON, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I210TOAR30ROW_NEON
ANY31CT(I210ToAR30Row_Any_NEON, I210ToAR30Row_NEON, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I410TOAR30ROW_NEON
ANY31CT(I410ToAR30Row_Any_NEON, I410ToAR30Row_NEON, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I212TOARGBROW_NEON
ANY31CT(I212ToARGBRow_Any_NEON, I212ToARGBRow_NEON, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_I212TOAR30ROW_NEON
ANY31CT(I212ToAR30Row_Any_NEON, I212ToAR30Row_NEON, 1, 0, uint16_t, 2, 4, 7)
#endif
#undef ANY31CT
// Any 3 planes to 1 plane with parameter
#define ANY31PT(NAMEANY, ANY_SIMD, STYPE, SBPP, DTYPE, BPP, MASK) \
void NAMEANY(const STYPE* r_buf, const STYPE* g_buf, const STYPE* b_buf, \
DTYPE* dst_ptr, int depth, int width) { \
SIMD_ALIGNED(STYPE vin[16 * 3]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin) / 3, \
"vin buffer too small"); \
SIMD_ALIGNED(DTYPE vout[64]); \
static_assert((MASK + 1) * BPP <= sizeof(vout), "vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(r_buf, g_buf, b_buf, dst_ptr, depth, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, r_buf + np, r * SBPP); \
memcpy(vin + 16, g_buf + np, r * SBPP); \
memcpy(vin + 32, b_buf + np, r * SBPP); \
ANY_SIMD(vin, vin + 16, vin + 32, vout, depth, MASK + 1); \
memcpy((uint8_t*)dst_ptr + np * BPP, vout, r * BPP); \
}
#ifdef HAS_MERGEXR30ROW_AVX2
ANY31PT(MergeXR30Row_Any_AVX2, MergeXR30Row_AVX2, uint16_t, 2, uint8_t, 4, 15)
#endif
#ifdef HAS_MERGEXR30ROW_NEON
ANY31PT(MergeXR30Row_Any_NEON, MergeXR30Row_NEON, uint16_t, 2, uint8_t, 4, 3)
ANY31PT(MergeXR30Row_10_Any_NEON,
MergeXR30Row_10_NEON,
uint16_t,
2,
uint8_t,
4,
7)
#endif
#ifdef HAS_MERGEXR64ROW_AVX2
ANY31PT(MergeXR64Row_Any_AVX2, MergeXR64Row_AVX2, uint16_t, 2, uint16_t, 8, 15)
#endif
#ifdef HAS_MERGEXR64ROW_NEON
ANY31PT(MergeXR64Row_Any_NEON, MergeXR64Row_NEON, uint16_t, 2, uint16_t, 8, 7)
#endif
#ifdef HAS_MERGEXRGB16TO8ROW_AVX2
ANY31PT(MergeXRGB16To8Row_Any_AVX2,
MergeXRGB16To8Row_AVX2,
uint16_t,
2,
uint8_t,
4,
15)
#endif
#ifdef HAS_MERGEXRGB16TO8ROW_NEON
ANY31PT(MergeXRGB16To8Row_Any_NEON,
MergeXRGB16To8Row_NEON,
uint16_t,
2,
uint8_t,
4,
7)
#endif
#undef ANY31PT
// Any 2 planes to 1.
#define ANY21(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, SBPP2, BPP, MASK) \
void NAMEANY(const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* dst_ptr, \
int width) { \
SIMD_ALIGNED(uint8_t vin[128 * 2]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin) / 2, \
"vin buffer too small"); \
static_assert(SS(MASK + 1, UVSHIFT) * SBPP2 <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[128]); \
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(y_buf, uv_buf, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np * SBPP, r * SBPP); \
memcpy(vin + 128, uv_buf + (np >> UVSHIFT) * SBPP2, \
SS(r, UVSHIFT) * SBPP2); \
ANY_SIMD(vin, vin + 128, vout, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
// Merge functions.
#ifdef HAS_MERGEUVROW_SSE2
ANY21(MergeUVRow_Any_SSE2, MergeUVRow_SSE2, 0, 1, 1, 2, 15)
#endif
#ifdef HAS_MERGEUVROW_AVX2
ANY21(MergeUVRow_Any_AVX2, MergeUVRow_AVX2, 0, 1, 1, 2, 31)
#endif
#ifdef HAS_MERGEUVROW_AVX512BW
ANY21(MergeUVRow_Any_AVX512BW, MergeUVRow_AVX512BW, 0, 1, 1, 2, 31)
#endif
#ifdef HAS_MERGEUVROW_NEON
ANY21(MergeUVRow_Any_NEON, MergeUVRow_NEON, 0, 1, 1, 2, 15)
#endif
#ifdef HAS_MERGEUVROW_LSX
ANY21(MergeUVRow_Any_LSX, MergeUVRow_LSX, 0, 1, 1, 2, 15)
#endif
#ifdef HAS_MERGEUVROW_LASX
ANY21(MergeUVRow_Any_LASX, MergeUVRow_LASX, 0, 1, 1, 2, 31)
#endif
#ifdef HAS_NV21TOYUV24ROW_NEON
ANY21(NV21ToYUV24Row_Any_NEON, NV21ToYUV24Row_NEON, 1, 1, 2, 3, 15)
#endif
#ifdef HAS_NV21TOYUV24ROW_SSSE3
ANY21(NV21ToYUV24Row_Any_SSSE3, NV21ToYUV24Row_SSSE3, 1, 1, 2, 3, 15)
#endif
#ifdef HAS_NV21TOYUV24ROW_AVX2
ANY21(NV21ToYUV24Row_Any_AVX2, NV21ToYUV24Row_AVX2, 1, 1, 2, 3, 31)
#endif
// Math functions.
#ifdef HAS_ARGBMULTIPLYROW_SSE2
ANY21(ARGBMultiplyRow_Any_SSE2, ARGBMultiplyRow_SSE2, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBADDROW_SSE2
ANY21(ARGBAddRow_Any_SSE2, ARGBAddRow_SSE2, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBSUBTRACTROW_SSE2
ANY21(ARGBSubtractRow_Any_SSE2, ARGBSubtractRow_SSE2, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBMULTIPLYROW_AVX2
ANY21(ARGBMultiplyRow_Any_AVX2, ARGBMultiplyRow_AVX2, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBADDROW_AVX2
ANY21(ARGBAddRow_Any_AVX2, ARGBAddRow_AVX2, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBSUBTRACTROW_AVX2
ANY21(ARGBSubtractRow_Any_AVX2, ARGBSubtractRow_AVX2, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBMULTIPLYROW_NEON
ANY21(ARGBMultiplyRow_Any_NEON, ARGBMultiplyRow_NEON, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBADDROW_NEON
ANY21(ARGBAddRow_Any_NEON, ARGBAddRow_NEON, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBSUBTRACTROW_NEON
ANY21(ARGBSubtractRow_Any_NEON, ARGBSubtractRow_NEON, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBBLENDROW_LSX
ANY21(ARGBBlendRow_Any_LSX, ARGBBlendRow_LSX, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBBLENDROW_LASX
ANY21(ARGBBlendRow_Any_LASX, ARGBBlendRow_LASX, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBMULTIPLYROW_LSX
ANY21(ARGBMultiplyRow_Any_LSX, ARGBMultiplyRow_LSX, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBMULTIPLYROW_LASX
ANY21(ARGBMultiplyRow_Any_LASX, ARGBMultiplyRow_LASX, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBADDROW_LSX
ANY21(ARGBAddRow_Any_LSX, ARGBAddRow_LSX, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBADDROW_LASX
ANY21(ARGBAddRow_Any_LASX, ARGBAddRow_LASX, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBSUBTRACTROW_LSX
ANY21(ARGBSubtractRow_Any_LSX, ARGBSubtractRow_LSX, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBSUBTRACTROW_LASX
ANY21(ARGBSubtractRow_Any_LASX, ARGBSubtractRow_LASX, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBALPHABLENDROW_SSSE3
ANY21(ARGBAlphaBlendRow_Any_SSSE3, ARGBAlphaBlendRow_SSSE3, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBALPHABLENDROW_AVX2
ANY21(ARGBAlphaBlendRow_Any_AVX2, ARGBAlphaBlendRow_AVX2, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBALPHABLENDROW_NEON
ANY21(ARGBAlphaBlendRow_Any_NEON, ARGBAlphaBlendRow_NEON, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBALPHABLENDROW_LSX
ANY21(ARGBAlphaBlendRow_Any_LSX, ARGBAlphaBlendRow_LSX, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_ARGBALPHABLENDROW_LASX
ANY21(ARGBAlphaBlendRow_Any_LASX, ARGBAlphaBlendRow_LASX, 0, 4, 4, 4, 7)
#endif
#ifdef HAS_ARGBALPHABLENDROW_WASMSIMD
ANY21(ARGBAlphaBlendRow_Any_WASMSIMD, ARGBAlphaBlendRow_WASMSIMD, 0, 4, 4, 4, 3)
#endif
#ifdef HAS_SOBELROW_SSE2
ANY21(SobelRow_Any_SSE2, SobelRow_SSE2, 0, 1, 1, 4, 15)
#endif
#ifdef HAS_SOBELROW_NEON
ANY21(SobelRow_Any_NEON, SobelRow_NEON, 0, 1, 1, 4, 7)
#endif
#ifdef HAS_SOBELROW_LSX
ANY21(SobelRow_Any_LSX, SobelRow_LSX, 0, 1, 1, 4, 7)
#endif
#ifdef HAS_SOBELROW_LASX
ANY21(SobelRow_Any_LASX, SobelRow_LASX, 0, 1, 1, 4, 15)
#endif
#ifdef HAS_SOBELTOPLANEROW_SSE2
ANY21(SobelToPlaneRow_Any_SSE2, SobelToPlaneRow_SSE2, 0, 1, 1, 1, 15)
#endif
#ifdef HAS_SOBELTOPLANEROW_NEON
ANY21(SobelToPlaneRow_Any_NEON, SobelToPlaneRow_NEON, 0, 1, 1, 1, 15)
#endif
#ifdef HAS_SOBELTOPLANEROW_LSX
ANY21(SobelToPlaneRow_Any_LSX, SobelToPlaneRow_LSX, 0, 1, 1, 1, 15)
#endif
#ifdef HAS_SOBELTOPLANEROW_LASX
ANY21(SobelToPlaneRow_Any_LASX, SobelToPlaneRow_LASX, 0, 1, 1, 1, 31)
#endif
#ifdef HAS_SOBELXYROW_SSE2
ANY21(SobelXYRow_Any_SSE2, SobelXYRow_SSE2, 0, 1, 1, 4, 15)
#endif
#ifdef HAS_SOBELXYROW_NEON
ANY21(SobelXYRow_Any_NEON, SobelXYRow_NEON, 0, 1, 1, 4, 7)
#endif
#ifdef HAS_SOBELXYROW_LSX
ANY21(SobelXYRow_Any_LSX, SobelXYRow_LSX, 0, 1, 1, 4, 7)
#endif
#ifdef HAS_SOBELXYROW_LASX
ANY21(SobelXYRow_Any_LASX, SobelXYRow_LASX, 0, 1, 1, 4, 15)
#endif
#ifdef HAS_MERGEUVROW_WASMSIMD
ANY21(MergeUVRow_Any_WASMSIMD, MergeUVRow_WASMSIMD, 0, 1, 1, 2, 15)
#endif
#undef ANY21
// Any 2 planes to 1 with stride
// width is measured in source pixels. 4 bytes contains 2 pixels
#define ANY21S(NAMEANY, ANY_SIMD, SBPP, BPP, MASK) \
void NAMEANY(const uint8_t* src_yuy2, int stride_yuy2, uint8_t* dst_uv, \
int width) { \
SIMD_ALIGNED(uint8_t vin[(MASK + 1) * SBPP * 2]); \
SIMD_ALIGNED(uint8_t vout[(MASK + 1) * BPP]); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int awidth = (width + 1) / 2; \
int r = awidth & MASK; \
int n = awidth & ~MASK; \
if (n > 0) { \
ANY_SIMD(src_yuy2, stride_yuy2, dst_uv, n * 2); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_yuy2 + np * SBPP, r * SBPP); \
memcpy(vin + (MASK + 1) * SBPP, src_yuy2 + stride_yuy2 + np * SBPP, \
r * SBPP); \
ANY_SIMD(vin, (MASK + 1) * SBPP, vout, MASK + 1); \
memcpy(dst_uv + np * BPP, vout, r * BPP); \
}
#ifdef HAS_YUY2TONVUVROW_NEON
ANY21S(YUY2ToNVUVRow_Any_NEON, YUY2ToNVUVRow_NEON, 4, 2, 7)
#endif
#ifdef HAS_YUY2TONVUVROW_SSE2
ANY21S(YUY2ToNVUVRow_Any_SSE2, YUY2ToNVUVRow_SSE2, 4, 2, 7)
#endif
#ifdef HAS_YUY2TONVUVROW_AVX2
ANY21S(YUY2ToNVUVRow_Any_AVX2, YUY2ToNVUVRow_AVX2, 4, 2, 15)
#endif
// Any 2 planes to 1 with yuvconstants
#define ANY21C(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, SBPP2, BPP, MASK) \
void NAMEANY(const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* dst_ptr, \
const struct YuvConstants* yuvconstants, int width) { \
SIMD_ALIGNED(uint8_t vin[128 * 2]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin) / 2, \
"vin buffer too small"); \
static_assert(SS(MASK + 1, UVSHIFT) * SBPP2 <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[128]); \
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(y_buf, uv_buf, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np * SBPP, r * SBPP); \
memcpy(vin + 128, uv_buf + (np >> UVSHIFT) * SBPP2, \
SS(r, UVSHIFT) * SBPP2); \
ANY_SIMD(vin, vin + 128, vout, yuvconstants, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
// Biplanar to RGB.
#ifdef HAS_NV12TOARGBROW_SSSE3
ANY21C(NV12ToARGBRow_Any_SSSE3, NV12ToARGBRow_SSSE3, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV12TOARGBROW_AVX2
ANY21C(NV12ToARGBRow_Any_AVX2, NV12ToARGBRow_AVX2, 1, 1, 2, 4, 15)
#endif
#ifdef HAS_NV12TOARGBROW_NEON
ANY21C(NV12ToARGBRow_Any_NEON, NV12ToARGBRow_NEON, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV12TOARGBROW_LSX
ANY21C(NV12ToARGBRow_Any_LSX, NV12ToARGBRow_LSX, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV12TOARGBROW_LASX
ANY21C(NV12ToARGBRow_Any_LASX, NV12ToARGBRow_LASX, 1, 1, 2, 4, 15)
#endif
#ifdef HAS_NV21TOARGBROW_SSSE3
ANY21C(NV21ToARGBRow_Any_SSSE3, NV21ToARGBRow_SSSE3, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV21TOARGBROW_AVX2
ANY21C(NV21ToARGBRow_Any_AVX2, NV21ToARGBRow_AVX2, 1, 1, 2, 4, 15)
#endif
#ifdef HAS_NV21TOARGBROW_NEON
ANY21C(NV21ToARGBRow_Any_NEON, NV21ToARGBRow_NEON, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV21TOARGBROW_LSX
ANY21C(NV21ToARGBRow_Any_LSX, NV21ToARGBRow_LSX, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV21TOARGBROW_LASX
ANY21C(NV21ToARGBRow_Any_LASX, NV21ToARGBRow_LASX, 1, 1, 2, 4, 15)
#endif
#ifdef HAS_NV12TORGB24ROW_NEON
ANY21C(NV12ToRGB24Row_Any_NEON, NV12ToRGB24Row_NEON, 1, 1, 2, 3, 7)
#endif
#ifdef HAS_NV21TORGB24ROW_NEON
ANY21C(NV21ToRGB24Row_Any_NEON, NV21ToRGB24Row_NEON, 1, 1, 2, 3, 7)
#endif
#ifdef HAS_NV12TORGB24ROW_SSSE3
ANY21C(NV12ToRGB24Row_Any_SSSE3, NV12ToRGB24Row_SSSE3, 1, 1, 2, 3, 15)
#endif
#ifdef HAS_NV21TORGB24ROW_SSSE3
ANY21C(NV21ToRGB24Row_Any_SSSE3, NV21ToRGB24Row_SSSE3, 1, 1, 2, 3, 15)
#endif
#ifdef HAS_NV12TORGB24ROW_AVX2
ANY21C(NV12ToRGB24Row_Any_AVX2, NV12ToRGB24Row_AVX2, 1, 1, 2, 3, 31)
#endif
#ifdef HAS_NV21TORGB24ROW_AVX2
ANY21C(NV21ToRGB24Row_Any_AVX2, NV21ToRGB24Row_AVX2, 1, 1, 2, 3, 31)
#endif
#ifdef HAS_NV12TORGB565ROW_SSSE3
ANY21C(NV12ToRGB565Row_Any_SSSE3, NV12ToRGB565Row_SSSE3, 1, 1, 2, 2, 7)
#endif
#ifdef HAS_NV12TORGB565ROW_AVX2
ANY21C(NV12ToRGB565Row_Any_AVX2, NV12ToRGB565Row_AVX2, 1, 1, 2, 2, 15)
#endif
#ifdef HAS_NV12TORGB565ROW_NEON
ANY21C(NV12ToRGB565Row_Any_NEON, NV12ToRGB565Row_NEON, 1, 1, 2, 2, 7)
#endif
#ifdef HAS_NV12TORGB565ROW_LSX
ANY21C(NV12ToRGB565Row_Any_LSX, NV12ToRGB565Row_LSX, 1, 1, 2, 2, 7)
#endif
#ifdef HAS_NV12TORGB565ROW_LASX
ANY21C(NV12ToRGB565Row_Any_LASX, NV12ToRGB565Row_LASX, 1, 1, 2, 2, 15)
#endif
#ifdef HAS_NV12TOARGBROW_WASMSIMD
ANY21C(NV12ToARGBRow_Any_WASMSIMD, NV12ToARGBRow_WASMSIMD, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV21TOARGBROW_WASMSIMD
ANY21C(NV21ToARGBRow_Any_WASMSIMD, NV21ToARGBRow_WASMSIMD, 1, 1, 2, 4, 7)
#endif
#ifdef HAS_NV12TORGB565ROW_WASMSIMD
ANY21C(NV12ToRGB565Row_Any_WASMSIMD, NV12ToRGB565Row_WASMSIMD, 1, 1, 2, 2, 7)
#endif
#undef ANY21C
// Any 2 planes of 16 bit to 1 with yuvconstants
#define ANY21CT(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, T, SBPP, BPP, MASK) \
void NAMEANY(const T* y_buf, const T* uv_buf, uint8_t* dst_ptr, \
const struct YuvConstants* yuvconstants, int width) { \
SIMD_ALIGNED(T vin[32 * 2]); \
static_assert(SS(MASK + 1, UVSHIFT) * SBPP * 2 <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert(SS(MASK + 1, DUVSHIFT) * 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(y_buf, uv_buf, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, y_buf + np, r * SBPP); \
memcpy(vin + 32, uv_buf + 2 * (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP * 2); \
ANY_SIMD(vin, vin + 32, vout, yuvconstants, MASK + 1); \
memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \
}
#ifdef HAS_P210TOAR30ROW_SSSE3
ANY21CT(P210ToAR30Row_Any_SSSE3, P210ToAR30Row_SSSE3, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P210TOARGBROW_SSSE3
ANY21CT(P210ToARGBRow_Any_SSSE3, P210ToARGBRow_SSSE3, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P210TOARGBROW_AVX2
ANY21CT(P210ToARGBRow_Any_AVX2, P210ToARGBRow_AVX2, 1, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_P210TOAR30ROW_AVX2
ANY21CT(P210ToAR30Row_Any_AVX2, P210ToAR30Row_AVX2, 1, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_P210TOAR30ROW_NEON
ANY21CT(P210ToAR30Row_Any_NEON, P210ToAR30Row_NEON, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P210TOARGBROW_NEON
ANY21CT(P210ToARGBRow_Any_NEON, P210ToARGBRow_NEON, 1, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P410TOAR30ROW_SSSE3
ANY21CT(P410ToAR30Row_Any_SSSE3, P410ToAR30Row_SSSE3, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P410TOARGBROW_SSSE3
ANY21CT(P410ToARGBRow_Any_SSSE3, P410ToARGBRow_SSSE3, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P410TOARGBROW_AVX2
ANY21CT(P410ToARGBRow_Any_AVX2, P410ToARGBRow_AVX2, 0, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_P410TOAR30ROW_AVX2
ANY21CT(P410ToAR30Row_Any_AVX2, P410ToAR30Row_AVX2, 0, 0, uint16_t, 2, 4, 15)
#endif
#ifdef HAS_P410TOAR30ROW_NEON
ANY21CT(P410ToAR30Row_Any_NEON, P410ToAR30Row_NEON, 0, 0, uint16_t, 2, 4, 7)
#endif
#ifdef HAS_P410TOARGBROW_NEON
ANY21CT(P410ToARGBRow_Any_NEON, P410ToARGBRow_NEON, 0, 0, uint16_t, 2, 4, 7)
#endif
#undef ANY21CT
// Any 2 16 bit planes with parameter to 1
#define ANY21PT(NAMEANY, ANY_SIMD, T, BPP, MASK) \
void NAMEANY(const T* src_u, const T* src_v, T* dst_uv, int depth, \
int width) { \
SIMD_ALIGNED(T vin[16 * 2]); \
static_assert((MASK + 1) * BPP <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(T vout[16]); \
static_assert((MASK + 1) * BPP * 2 <= 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_u, src_v, dst_uv, depth, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_u + np, r * BPP); \
memcpy(vin + 16, src_v + np, r * BPP); \
ANY_SIMD(vin, vin + 16, vout, depth, MASK + 1); \
memcpy(dst_uv + np * 2, vout, r * BPP * 2); \
}
#ifdef HAS_MERGEUVROW_16_AVX2
ANY21PT(MergeUVRow_16_Any_AVX2, MergeUVRow_16_AVX2, uint16_t, 2, 7)
#endif
#ifdef HAS_MERGEUVROW_16_NEON
ANY21PT(MergeUVRow_16_Any_NEON, MergeUVRow_16_NEON, uint16_t, 2, 7)
#endif
#undef ANY21CT
// Any 1 to 1.
#define ANY11(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, int width) { \
SIMD_ALIGNED(uint8_t vin[256]); \
static_assert(SS(MASK + 1, UVSHIFT) * SBPP <= sizeof(vin), \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256]); \
static_assert((MASK + 1) * BPP <= sizeof(vout), "vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(src_ptr, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \
ANY_SIMD(vin, vout, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
#ifdef HAS_COPYROW_AVX
ANY11(CopyRow_Any_AVX, CopyRow_AVX, 0, 1, 1, 63)
#endif
#ifdef HAS_COPYROW_SSE2
ANY11(CopyRow_Any_SSE2, CopyRow_SSE2, 0, 1, 1, 31)
#endif
#ifdef HAS_COPYROW_NEON
ANY11(CopyRow_Any_NEON, CopyRow_NEON, 0, 1, 1, 31)
#endif
#ifdef HAS_COPYROW_LSX
ANY11(CopyRow_Any_LSX, CopyRow_LSX, 0, 1, 1, 15)
#endif
#ifdef HAS_COPYROW_LASX
ANY11(CopyRow_Any_LASX, CopyRow_LASX, 0, 1, 1, 31)
#endif
#if defined(HAS_ARGBTORGB24ROW_SSSE3)
ANY11(ARGBToRGB24Row_Any_SSSE3, ARGBToRGB24Row_SSSE3, 0, 4, 3, 15)
ANY11(ARGBToRAWRow_Any_SSSE3, ARGBToRAWRow_SSSE3, 0, 4, 3, 15)
#endif
#if defined(HAS_ARGBTORGB24ROW_AVX2)
ANY11(ARGBToRGB24Row_Any_AVX2, ARGBToRGB24Row_AVX2, 0, 4, 3, 31)
#endif
#if defined(HAS_ARGBTORAWROW_AVX2)
ANY11(ARGBToRAWRow_Any_AVX2, ARGBToRAWRow_AVX2, 0, 4, 3, 31)
#endif
#if defined(HAS_ARGBTORGB565ROW_AVX2)
ANY11(ARGBToRGB565Row_Any_AVX2, ARGBToRGB565Row_AVX2, 0, 4, 2, 7)
#endif
#if defined(HAS_ARGBTOARGB1555ROW_AVX2)
ANY11(ARGBToARGB1555Row_Any_AVX2, ARGBToARGB1555Row_AVX2, 0, 4, 2, 7)
#endif
#if defined(HAS_ARGBTOARGB4444ROW_AVX2)
ANY11(ARGBToARGB4444Row_Any_AVX2, ARGBToARGB4444Row_AVX2, 0, 4, 2, 7)
#endif
#if defined(HAS_ABGRTOAR30ROW_SSSE3)
ANY11(ABGRToAR30Row_Any_SSSE3, ABGRToAR30Row_SSSE3, 0, 4, 4, 3)
#endif
#if defined(HAS_ABGRTOAR30ROW_NEON)
ANY11(ABGRToAR30Row_Any_NEON, ABGRToAR30Row_NEON, 0, 4, 4, 7)
#endif
#if defined(HAS_ARGBTOAR30ROW_NEON)
ANY11(ARGBToAR30Row_Any_NEON, ARGBToAR30Row_NEON, 0, 4, 4, 7)
#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)
ANY11(ARGBToAR30Row_Any_SSSE3, ARGBToAR30Row_SSSE3, 0, 4, 4, 3)
#endif
#if defined(HAS_ABGRTOAR30ROW_AVX2)
ANY11(ABGRToAR30Row_Any_AVX2, ABGRToAR30Row_AVX2, 0, 4, 4, 7)
#endif
#if defined(HAS_ARGBTOAR30ROW_AVX2)
ANY11(ARGBToAR30Row_Any_AVX2, ARGBToAR30Row_AVX2, 0, 4, 4, 7)
#endif
#if defined(HAS_J400TOARGBROW_AVX512BW)
ANY11(J400ToARGBRow_Any_AVX512BW, J400ToARGBRow_AVX512BW, 0, 1, 4, 31)
#endif
#if defined(HAS_J400TOARGBROW_AVX2)
ANY11(J400ToARGBRow_Any_AVX2, J400ToARGBRow_AVX2, 0, 1, 4, 15)
#endif
#if defined(HAS_RGB24TOARGBROW_SSSE3)
ANY11(RGB24ToARGBRow_Any_SSSE3, RGB24ToARGBRow_SSSE3, 0, 3, 4, 15)
ANY11(RAWToARGBRow_Any_SSSE3, RAWToARGBRow_SSSE3, 0, 3, 4, 15)
#endif
#if defined(HAS_RAWTOARGBROW_AVX2)
ANY11(RAWToARGBRow_Any_AVX2, RAWToARGBRow_AVX2, 0, 3, 4, 31)
#endif
#if defined(HAS_RGB24TOARGBROW_AVX2)
ANY11(RGB24ToARGBRow_Any_AVX2, RGB24ToARGBRow_AVX2, 0, 3, 4, 31)
#endif
#if defined(HAS_RAWTORGBAROW_SSSE3)
ANY11(RAWToRGBARow_Any_SSSE3, RAWToRGBARow_SSSE3, 0, 3, 4, 15)
#endif
#if defined(HAS_RAWTORGB24ROW_SSSE3)
ANY11(RAWToRGB24Row_Any_SSSE3, RAWToRGB24Row_SSSE3, 0, 3, 3, 7)
#endif
#if defined(HAS_RAWTORGB24ROW_AVX2)
ANY11(RAWToRGB24Row_Any_AVX2, RAWToRGB24Row_AVX2, 0, 3, 3, 31)
#endif
#if defined(HAS_RAWTORGB24ROW_AVX512BW)
ANY11(RAWToRGB24Row_Any_AVX512BW, RAWToRGB24Row_AVX512BW, 0, 3, 3, 63)
#endif
#if defined(HAS_RAWTORGB24ROW_AVX512VBMI)
ANY11(RAWToRGB24Row_Any_AVX512VBMI, RAWToRGB24Row_AVX512VBMI, 0, 3, 3, 63)
#endif
#if defined(HAS_RGB565TOARGBROW_AVX2)
ANY11(RGB565ToARGBRow_Any_AVX2, RGB565ToARGBRow_AVX2, 0, 2, 4, 15)
#endif
#if defined(HAS_ARGB1555TOARGBROW_AVX2)
ANY11(ARGB1555ToARGBRow_Any_AVX2, ARGB1555ToARGBRow_AVX2, 0, 2, 4, 15)
#endif
#if defined(HAS_ARGB4444TOARGBROW_AVX2)
ANY11(ARGB4444ToARGBRow_Any_AVX2, ARGB4444ToARGBRow_AVX2, 0, 2, 4, 15)
#endif
#if defined(HAS_ARGBTORGB24ROW_NEON)
ANY11(ARGBToRGB24Row_Any_NEON, ARGBToRGB24Row_NEON, 0, 4, 3, 15)
ANY11(ARGBToRAWRow_Any_NEON, ARGBToRAWRow_NEON, 0, 4, 3, 7)
ANY11(ARGBToRGB565Row_Any_NEON, ARGBToRGB565Row_NEON, 0, 4, 2, 7)
ANY11(ARGBToARGB1555Row_Any_NEON, ARGBToARGB1555Row_NEON, 0, 4, 2, 7)
ANY11(ARGBToARGB4444Row_Any_NEON, ARGBToARGB4444Row_NEON, 0, 4, 2, 7)
ANY11(J400ToARGBRow_Any_NEON, J400ToARGBRow_NEON, 0, 1, 4, 7)
#endif
#if defined(HAS_ARGBTORGB24ROW_LSX)
ANY11(ARGBToRGB24Row_Any_LSX, ARGBToRGB24Row_LSX, 0, 4, 3, 15)
ANY11(ARGBToRAWRow_Any_LSX, ARGBToRAWRow_LSX, 0, 4, 3, 15)
ANY11(ARGBToRGB565Row_Any_LSX, ARGBToRGB565Row_LSX, 0, 4, 2, 7)
ANY11(ARGBToARGB1555Row_Any_LSX, ARGBToARGB1555Row_LSX, 0, 4, 2, 7)
ANY11(ARGBToARGB4444Row_Any_LSX, ARGBToARGB4444Row_LSX, 0, 4, 2, 7)
#endif
#if defined(HAS_ARGBTORGB24ROW_LASX)
ANY11(ARGBToRGB24Row_Any_LASX, ARGBToRGB24Row_LASX, 0, 4, 3, 31)
ANY11(ARGBToRAWRow_Any_LASX, ARGBToRAWRow_LASX, 0, 4, 3, 31)
ANY11(ARGBToRGB565Row_Any_LASX, ARGBToRGB565Row_LASX, 0, 4, 2, 15)
ANY11(ARGBToARGB1555Row_Any_LASX, ARGBToARGB1555Row_LASX, 0, 4, 2, 15)
ANY11(ARGBToARGB4444Row_Any_LASX, ARGBToARGB4444Row_LASX, 0, 4, 2, 15)
#endif
#if defined(HAS_J400TOARGBROW_LSX)
ANY11(J400ToARGBRow_Any_LSX, J400ToARGBRow_LSX, 0, 1, 4, 7)
#endif
#if defined(HAS_J400TOARGBROW_LASX)
ANY11(J400ToARGBRow_Any_LASX, J400ToARGBRow_LASX, 0, 1, 4, 15)
#endif
#if defined(HAS_RAWTORGB24ROW_NEON)
ANY11(RAWToRGB24Row_Any_NEON, RAWToRGB24Row_NEON, 0, 3, 3, 15)
#endif
#if defined(HAS_RAWTORGB24ROW_LSX)
ANY11(RAWToRGB24Row_Any_LSX, RAWToRGB24Row_LSX, 0, 3, 3, 15)
#endif
#if defined(HAS_RAWTORGB24ROW_LASX)
ANY11(RAWToRGB24Row_Any_LASX, RAWToRGB24Row_LASX, 0, 3, 3, 31)
#endif
#if defined(HAS_RAWTORGB24ROW_WASMSIMD)
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)
#endif
#ifdef HAS_YUY2TOYROW_AVX2
ANY11(YUY2ToYRow_Any_AVX2, YUY2ToYRow_AVX2, 1, 4, 1, 31)
#endif
#ifdef HAS_YUY2TOYROW_SSE2
ANY11(YUY2ToYRow_Any_SSE2, YUY2ToYRow_SSE2, 1, 4, 1, 15)
ANY11(UYVYToYRow_Any_SSE2, UYVYToYRow_SSE2, 1, 4, 1, 15)
#endif
#ifdef HAS_RGB565TOYROW_NEON
ANY11(RGB565ToYRow_Any_NEON, RGB565ToYRow_NEON, 0, 2, 1, 15)
#endif
#ifdef HAS_RGB565TOYROW_LSX
ANY11(RGB565ToYRow_Any_LSX, RGB565ToYRow_LSX, 0, 2, 1, 7)
#endif
#ifdef HAS_RGB565TOYROW_LASX
ANY11(RGB565ToYRow_Any_LASX, RGB565ToYRow_LASX, 0, 2, 1, 15)
#endif
#ifdef HAS_ARGB1555TOYROW_NEON
#ifdef __aarch64__
ANY11(ARGB1555ToYRow_Any_NEON, ARGB1555ToYRow_NEON, 0, 2, 1, 15)
#else
ANY11(ARGB1555ToYRow_Any_NEON, ARGB1555ToYRow_NEON, 0, 2, 1, 7)
#endif
#endif
#ifdef HAS_ARGB1555TOYROW_LSX
ANY11(ARGB1555ToYRow_Any_LSX, ARGB1555ToYRow_LSX, 0, 2, 1, 7)
#endif
#ifdef HAS_ARGB1555TOYROW_LASX
ANY11(ARGB1555ToYRow_Any_LASX, ARGB1555ToYRow_LASX, 0, 2, 1, 15)
#endif
#ifdef HAS_ARGB4444TOYROW_NEON
#ifdef __aarch64__
ANY11(ARGB4444ToYRow_Any_NEON, ARGB4444ToYRow_NEON, 0, 2, 1, 15)
#else
ANY11(ARGB4444ToYRow_Any_NEON, ARGB4444ToYRow_NEON, 0, 2, 1, 7)
#endif
#endif
#ifdef HAS_YUY2TOYROW_NEON
ANY11(YUY2ToYRow_Any_NEON, YUY2ToYRow_NEON, 1, 4, 1, 15)
#endif
#ifdef HAS_UYVYTOYROW_NEON
ANY11(UYVYToYRow_Any_NEON, UYVYToYRow_NEON, 1, 4, 1, 15)
#endif
#ifdef HAS_YUY2TOYROW_LSX
ANY11(YUY2ToYRow_Any_LSX, YUY2ToYRow_LSX, 1, 4, 1, 15)
#endif
#ifdef HAS_YUY2TOYROW_LASX
ANY11(YUY2ToYRow_Any_LASX, YUY2ToYRow_LASX, 1, 4, 1, 31)
#endif
#ifdef HAS_UYVYTOYROW_LSX
ANY11(UYVYToYRow_Any_LSX, UYVYToYRow_LSX, 1, 4, 1, 15)
#endif
#ifdef HAS_UYVYTOYROW_LASX
ANY11(UYVYToYRow_Any_LASX, UYVYToYRow_LASX, 1, 4, 1, 31)
#endif
#ifdef HAS_AYUVTOYROW_NEON
ANY11(AYUVToYRow_Any_NEON, AYUVToYRow_NEON, 0, 4, 1, 15)
#endif
#ifdef HAS_SWAPUVROW_SSSE3
ANY11(SwapUVRow_Any_SSSE3, SwapUVRow_SSSE3, 0, 2, 2, 15)
#endif
#ifdef HAS_SWAPUVROW_AVX2
ANY11(SwapUVRow_Any_AVX2, SwapUVRow_AVX2, 0, 2, 2, 31)
#endif
#ifdef HAS_SWAPUVROW_NEON
ANY11(SwapUVRow_Any_NEON, SwapUVRow_NEON, 0, 2, 2, 15)
#endif
#ifdef HAS_RGB24TOARGBROW_NEON
ANY11(RGB24ToARGBRow_Any_NEON, RGB24ToARGBRow_NEON, 0, 3, 4, 7)
#endif
#ifdef HAS_RGB24TOARGBROW_LSX
ANY11(RGB24ToARGBRow_Any_LSX, RGB24ToARGBRow_LSX, 0, 3, 4, 15)
#endif
#ifdef HAS_RGB24TOARGBROW_LASX
ANY11(RGB24ToARGBRow_Any_LASX, RGB24ToARGBRow_LASX, 0, 3, 4, 31)
#endif
#ifdef HAS_RAWTOARGBROW_NEON
ANY11(RAWToARGBRow_Any_NEON, RAWToARGBRow_NEON, 0, 3, 4, 7)
#endif
#ifdef HAS_RAWTORGBAROW_NEON
ANY11(RAWToRGBARow_Any_NEON, RAWToRGBARow_NEON, 0, 3, 4, 7)
#endif
#ifdef HAS_RAWTOARGBROW_LSX
ANY11(RAWToARGBRow_Any_LSX, RAWToARGBRow_LSX, 0, 3, 4, 15)
#endif
#ifdef HAS_RAWTOARGBROW_LASX
ANY11(RAWToARGBRow_Any_LASX, RAWToARGBRow_LASX, 0, 3, 4, 31)
#endif
#ifdef HAS_RGB565TOARGBROW_NEON
ANY11(RGB565ToARGBRow_Any_NEON, RGB565ToARGBRow_NEON, 0, 2, 4, 15)
#endif
#ifdef HAS_RGB565TOARGBROW_LSX
ANY11(RGB565ToARGBRow_Any_LSX, RGB565ToARGBRow_LSX, 0, 2, 4, 7)
#endif
#ifdef HAS_RGB565TOARGBROW_LASX
ANY11(RGB565ToARGBRow_Any_LASX, RGB565ToARGBRow_LASX, 0, 2, 4, 15)
#endif
#ifdef HAS_ARGB1555TOARGBROW_NEON
ANY11(ARGB1555ToARGBRow_Any_NEON, ARGB1555ToARGBRow_NEON, 0, 2, 4, 15)
#endif
#ifdef HAS_ARGB1555TOARGBROW_LSX
ANY11(ARGB1555ToARGBRow_Any_LSX, ARGB1555ToARGBRow_LSX, 0, 2, 4, 7)
#endif
#ifdef HAS_ARGB1555TOARGBROW_LASX
ANY11(ARGB1555ToARGBRow_Any_LASX, ARGB1555ToARGBRow_LASX, 0, 2, 4, 15)
#endif
#ifdef HAS_ARGB4444TOARGBROW_NEON
ANY11(ARGB4444ToARGBRow_Any_NEON, ARGB4444ToARGBRow_NEON, 0, 2, 4, 7)
#endif
#ifdef HAS_ARGB4444TOARGBROW_LSX
ANY11(ARGB4444ToARGBRow_Any_LSX, ARGB4444ToARGBRow_LSX, 0, 2, 4, 7)
#endif
#ifdef HAS_ARGB4444TOARGBROW_LASX
ANY11(ARGB4444ToARGBRow_Any_LASX, ARGB4444ToARGBRow_LASX, 0, 2, 4, 15)
#endif
#ifdef HAS_ARGBATTENUATEROW_SSSE3
ANY11(ARGBAttenuateRow_Any_SSSE3, ARGBAttenuateRow_SSSE3, 0, 4, 4, 3)
#endif
#ifdef HAS_ARGBUNATTENUATEROW_SSE2
ANY11(ARGBUnattenuateRow_Any_SSE2, ARGBUnattenuateRow_SSE2, 0, 4, 4, 3)
#endif
#ifdef HAS_ARGBATTENUATEROW_AVX2
ANY11(ARGBAttenuateRow_Any_AVX2, ARGBAttenuateRow_AVX2, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBUNATTENUATEROW_AVX2
ANY11(ARGBUnattenuateRow_Any_AVX2, ARGBUnattenuateRow_AVX2, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBATTENUATEROW_NEON
ANY11(ARGBAttenuateRow_Any_NEON, ARGBAttenuateRow_NEON, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBUNATTENUATEROW_NEON
ANY11(ARGBUnattenuateRow_Any_NEON, ARGBUnattenuateRow_NEON, 0, 4, 4, 3)
#endif
#ifdef HAS_ARGBATTENUATEROW_LSX
ANY11(ARGBAttenuateRow_Any_LSX, ARGBAttenuateRow_LSX, 0, 4, 4, 3)
#endif
#ifdef HAS_ARGBATTENUATEROW_LASX
ANY11(ARGBAttenuateRow_Any_LASX, ARGBAttenuateRow_LASX, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBEXTRACTALPHAROW_SSE2
ANY11(ARGBExtractAlphaRow_Any_SSE2, ARGBExtractAlphaRow_SSE2, 0, 4, 1, 7)
#endif
#ifdef HAS_ARGBEXTRACTALPHAROW_AVX2
ANY11(ARGBExtractAlphaRow_Any_AVX2, ARGBExtractAlphaRow_AVX2, 0, 4, 1, 31)
#endif
#ifdef HAS_ARGBEXTRACTALPHAROW_NEON
ANY11(ARGBExtractAlphaRow_Any_NEON, ARGBExtractAlphaRow_NEON, 0, 4, 1, 15)
#endif
#ifdef HAS_ARGBEXTRACTALPHAROW_LSX
ANY11(ARGBExtractAlphaRow_Any_LSX, ARGBExtractAlphaRow_LSX, 0, 4, 1, 7)
#endif
#ifdef HAS_ARGBEXTRACTALPHAROW_LASX
ANY11(ARGBExtractAlphaRow_Any_LASX, ARGBExtractAlphaRow_LASX, 0, 4, 1, 15)
#endif
#ifdef HAS_ARGBEXTRACTALPHAROW_WASMSIMD
ANY11(ARGBExtractAlphaRow_Any_WASMSIMD,
ARGBExtractAlphaRow_WASMSIMD,
0,
4,
1,
15)
#endif
#ifdef HAS_RAWTOARGBROW_WASMSIMD
ANY11(RAWToARGBRow_Any_WASMSIMD, RAWToARGBRow_WASMSIMD, 0, 3, 4, 15)
#endif
#ifdef HAS_RGB24TOARGBROW_WASMSIMD
ANY11(RGB24ToARGBRow_Any_WASMSIMD, RGB24ToARGBRow_WASMSIMD, 0, 3, 4, 15)
#endif
#ifdef HAS_SWAPUVROW_WASMSIMD
ANY11(SwapUVRow_Any_WASMSIMD, SwapUVRow_WASMSIMD, 0, 2, 2, 15)
#endif
#ifdef HAS_J400TOARGBROW_WASMSIMD
ANY11(J400ToARGBRow_Any_WASMSIMD, J400ToARGBRow_WASMSIMD, 0, 1, 4, 15)
#endif
#ifdef HAS_RGB565TOARGBROW_WASMSIMD
ANY11(RGB565ToARGBRow_Any_WASMSIMD, RGB565ToARGBRow_WASMSIMD, 0, 2, 4, 7)
#endif
#ifdef HAS_ARGB1555TOARGBROW_WASMSIMD
ANY11(ARGB1555ToARGBRow_Any_WASMSIMD, ARGB1555ToARGBRow_WASMSIMD, 0, 2, 4, 7)
#endif
#ifdef HAS_ARGB4444TOARGBROW_WASMSIMD
ANY11(ARGB4444ToARGBRow_Any_WASMSIMD, ARGB4444ToARGBRow_WASMSIMD, 0, 2, 4, 7)
#endif
#ifdef HAS_ARGBTORGB565ROW_WASMSIMD
ANY11(ARGBToRGB565Row_Any_WASMSIMD, ARGBToRGB565Row_WASMSIMD, 0, 4, 2, 7)
#endif
#ifdef HAS_ARGBTOARGB1555ROW_WASMSIMD
ANY11(ARGBToARGB1555Row_Any_WASMSIMD, ARGBToARGB1555Row_WASMSIMD, 0, 4, 2, 7)
#endif
#ifdef HAS_ARGBTOARGB4444ROW_WASMSIMD
ANY11(ARGBToARGB4444Row_Any_WASMSIMD, ARGBToARGB4444Row_WASMSIMD, 0, 4, 2, 7)
#endif
#undef ANY11
// Any 1 to 1 blended. Destination is read, modify, write.
#define ANY11B(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, int width) { \
SIMD_ALIGNED(uint8_t vin[64]); \
static_assert(SS(MASK + 1, UVSHIFT) * SBPP <= sizeof(vin), \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_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, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \
memcpy(vout, dst_ptr + np * BPP, r * BPP); \
ANY_SIMD(vin, vout, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
#ifdef HAS_ARGBCOPYALPHAROW_AVX2
ANY11B(ARGBCopyAlphaRow_Any_AVX2, ARGBCopyAlphaRow_AVX2, 0, 4, 4, 15)
#endif
#ifdef HAS_ARGBCOPYALPHAROW_SSE2
ANY11B(ARGBCopyAlphaRow_Any_SSE2, ARGBCopyAlphaRow_SSE2, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBCOPYALPHAROW_NEON
ANY11B(ARGBCopyAlphaRow_Any_NEON, ARGBCopyAlphaRow_NEON, 0, 4, 4, 7)
#endif
#ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2
ANY11B(ARGBCopyYToAlphaRow_Any_AVX2, ARGBCopyYToAlphaRow_AVX2, 0, 1, 4, 15)
#endif
#ifdef HAS_ARGBCOPYYTOALPHAROW_SSE2
ANY11B(ARGBCopyYToAlphaRow_Any_SSE2, ARGBCopyYToAlphaRow_SSE2, 0, 1, 4, 7)
#endif
#ifdef HAS_ARGBCOPYYTOALPHAROW_NEON
ANY11B(ARGBCopyYToAlphaRow_Any_NEON, ARGBCopyYToAlphaRow_NEON, 0, 1, 4, 15)
#endif
#ifdef HAS_ARGBCOPYYTOALPHAROW_WASMSIMD
ANY11B(ARGBCopyYToAlphaRow_Any_WASMSIMD,
ARGBCopyYToAlphaRow_WASMSIMD,
0,
1,
4,
15)
#endif
#undef ANY11B
// Any 1 to 1 with parameter.
#define ANY11P(NAMEANY, ANY_SIMD, T, SBPP, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, T param, int width) { \
SIMD_ALIGNED(uint8_t vin[(MASK + 1) * SBPP]); \
SIMD_ALIGNED(uint8_t vout[(MASK + 1) * BPP]); \
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, dst_ptr, param, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * SBPP, r * SBPP); \
ANY_SIMD(vin, vout, param, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
#if defined(HAS_I400TOARGBROW_SSE2)
ANY11P(I400ToARGBRow_Any_SSE2,
I400ToARGBRow_SSE2,
const struct YuvConstants*,
1,
4,
7)
#endif
#if defined(HAS_I400TOARGBROW_AVX2)
ANY11P(I400ToARGBRow_Any_AVX2,
I400ToARGBRow_AVX2,
const struct YuvConstants*,
1,
4,
15)
#endif
#if defined(HAS_I400TOARGBROW_NEON)
ANY11P(I400ToARGBRow_Any_NEON,
I400ToARGBRow_NEON,
const struct YuvConstants*,
1,
4,
7)
#endif
#if defined(HAS_I400TOARGBROW_LSX)
ANY11P(I400ToARGBRow_Any_LSX,
I400ToARGBRow_LSX,
const struct YuvConstants*,
1,
4,
7)
#endif
#if defined(HAS_I400TOARGBROW_LASX)
ANY11P(I400ToARGBRow_Any_LASX,
I400ToARGBRow_LASX,
const struct YuvConstants*,
1,
4,
15)
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
ANY11P(ARGBToRGB565DitherRow_Any_AVX2,
ARGBToRGB565DitherRow_AVX2,
const uint32_t,
4,
2,
7)
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_NEON)
ANY11P(ARGBToRGB565DitherRow_Any_NEON,
ARGBToRGB565DitherRow_NEON,
const uint32_t,
4,
2,
7)
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_LSX)
ANY11P(ARGBToRGB565DitherRow_Any_LSX,
ARGBToRGB565DitherRow_LSX,
const uint32_t,
4,
2,
3)
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_LASX)
ANY11P(ARGBToRGB565DitherRow_Any_LASX,
ARGBToRGB565DitherRow_LASX,
const uint32_t,
4,
2,
7)
#endif
#ifdef HAS_ARGBSHUFFLEROW_SSSE3
ANY11P(ARGBShuffleRow_Any_SSSE3, ARGBShuffleRow_SSSE3, const uint8_t*, 4, 4, 7)
#endif
#ifdef HAS_ARGBSHUFFLEROW_AVX2
ANY11P(ARGBShuffleRow_Any_AVX2, ARGBShuffleRow_AVX2, const uint8_t*, 4, 4, 15)
#endif
#ifdef HAS_ARGBSHUFFLEROW_NEON
ANY11P(ARGBShuffleRow_Any_NEON, ARGBShuffleRow_NEON, const uint8_t*, 4, 4, 3)
#endif
#ifdef HAS_ARGBSHUFFLEROW_LSX
ANY11P(ARGBShuffleRow_Any_LSX, ARGBShuffleRow_LSX, const uint8_t*, 4, 4, 3)
#endif
#ifdef HAS_ARGBSHUFFLEROW_LASX
ANY11P(ARGBShuffleRow_Any_LASX, ARGBShuffleRow_LASX, const uint8_t*, 4, 4, 7)
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_WASMSIMD)
ANY11P(ARGBToRGB565DitherRow_Any_WASMSIMD,
ARGBToRGB565DitherRow_WASMSIMD,
const uint32_t,
4,
2,
7)
#endif
#ifdef HAS_ARGBSHUFFLEROW_WASMSIMD
ANY11P(ARGBShuffleRow_Any_WASMSIMD,
ARGBShuffleRow_WASMSIMD,
const uint8_t*,
4,
4,
3)
#endif
#ifdef HAS_ARGBORROW_SSE2
ANY11P(ARGBOrRow_Any_SSE2, ARGBOrRow_SSE2, const uint32_t, 4, 4, 3)
#endif
#ifdef HAS_ARGBORROW_AVX2
ANY11P(ARGBOrRow_Any_AVX2, ARGBOrRow_AVX2, const uint32_t, 4, 4, 7)
#endif
#ifdef HAS_ARGBORROW_NEON
ANY11P(ARGBOrRow_Any_NEON, ARGBOrRow_NEON, const uint32_t, 4, 4, 7)
#endif
#ifdef HAS_ARGBORROW_LSX
ANY11P(ARGBOrRow_Any_LSX, ARGBOrRow_LSX, const uint32_t, 4, 4, 3)
#endif
#ifdef HAS_ARGBORROW_LASX
ANY11P(ARGBOrRow_Any_LASX, ARGBOrRow_LASX, const uint32_t, 4, 4, 7)
#endif
#ifdef HAS_ARGBORROW_WASMSIMD
ANY11P(ARGBOrRow_Any_WASMSIMD, ARGBOrRow_WASMSIMD, const uint32_t, 4, 4, 3)
#endif
#ifdef HAS_ARGBPOLYNOMIALROW_NEON
ANY11P(ARGBPolynomialRow_Any_NEON,
ARGBPolynomialRow_NEON,
const float*,
4,
4,
1)
#endif
#undef ANY11P
#undef ANY11P
// Any 1 to 1 with type
#define ANY11T(NAMEANY, ANY_SIMD, SBPP, BPP, STYPE, DTYPE, MASK) \
void NAMEANY(const STYPE* src_ptr, DTYPE* dst_ptr, int width) { \
SIMD_ALIGNED(uint8_t vin[(MASK + 1) * SBPP]); \
SIMD_ALIGNED(uint8_t vout[(MASK + 1) * BPP]); \
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, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, (uint8_t*)(src_ptr) + np * SBPP, r * SBPP); \
ANY_SIMD((STYPE*)vin, (DTYPE*)vout, MASK + 1); \
memcpy((uint8_t*)(dst_ptr) + np * BPP, vout, r * BPP); \
}
#ifdef HAS_ARGBTOAR64ROW_SSSE3
ANY11T(ARGBToAR64Row_Any_SSSE3, ARGBToAR64Row_SSSE3, 4, 8, uint8_t, uint16_t, 3)
#endif
#ifdef HAS_ARGBTOAB64ROW_SSSE3
ANY11T(ARGBToAB64Row_Any_SSSE3, ARGBToAB64Row_SSSE3, 4, 8, uint8_t, uint16_t, 3)
#endif
#ifdef HAS_AR64TOARGBROW_SSSE3
ANY11T(AR64ToARGBRow_Any_SSSE3, AR64ToARGBRow_SSSE3, 8, 4, uint16_t, uint8_t, 3)
#endif
#ifdef HAS_AB64TOARGBROW_SSSE3
ANY11T(AB64ToARGBRow_Any_SSSE3, AB64ToARGBRow_SSSE3, 8, 4, uint16_t, uint8_t, 3)
#endif
#ifdef HAS_ARGBTOAR64ROW_AVX2
ANY11T(ARGBToAR64Row_Any_AVX2, ARGBToAR64Row_AVX2, 4, 8, uint8_t, uint16_t, 7)
#endif
#ifdef HAS_ARGBTOAB64ROW_AVX2
ANY11T(ARGBToAB64Row_Any_AVX2, ARGBToAB64Row_AVX2, 4, 8, uint8_t, uint16_t, 7)
#endif
#ifdef HAS_AR64TOARGBROW_AVX2
ANY11T(AR64ToARGBRow_Any_AVX2, AR64ToARGBRow_AVX2, 8, 4, uint16_t, uint8_t, 7)
#endif
#ifdef HAS_AB64TOARGBROW_AVX2
ANY11T(AB64ToARGBRow_Any_AVX2, AB64ToARGBRow_AVX2, 8, 4, uint16_t, uint8_t, 7)
#endif
#ifdef HAS_ARGBTOAR64ROW_NEON
ANY11T(ARGBToAR64Row_Any_NEON, ARGBToAR64Row_NEON, 4, 8, uint8_t, uint16_t, 7)
#endif
#ifdef HAS_ARGBTOAB64ROW_NEON
ANY11T(ARGBToAB64Row_Any_NEON, ARGBToAB64Row_NEON, 4, 8, uint8_t, uint16_t, 7)
#endif
#ifdef HAS_AR64TOARGBROW_NEON
ANY11T(AR64ToARGBRow_Any_NEON, AR64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
#endif
#ifdef HAS_AB64TOARGBROW_NEON
ANY11T(AB64ToARGBRow_Any_NEON, AB64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
#endif
#ifdef HAS_COPYROW_16_NEON
ANY11T(CopyRow_16_Any_NEON, CopyRow_16_NEON, 2, 2, uint16_t, uint16_t, 15)
#endif
#undef ANY11T
// Any 1 to 1 with parameter and shorts. BPP measures in shorts.
#define ANY11C(NAMEANY, ANY_SIMD, SBPP, BPP, STYPE, DTYPE, MASK) \
void NAMEANY(const STYPE* src_ptr, DTYPE* dst_ptr, int value, int width) { \
SIMD_ALIGNED(STYPE vin[64]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(DTYPE 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, dst_ptr, value, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np, r * SBPP); \
ANY_SIMD(vin, vout, value, MASK + 1); \
memcpy(dst_ptr + np, vout, r * BPP); \
}
#ifdef HAS_CONVERT16TO8ROW_SSSE3
ANY11C(Convert16To8Row_Any_SSSE3,
Convert16To8Row_SSSE3,
2,
1,
uint16_t,
uint8_t,
15)
#endif
#ifdef HAS_CONVERT16TO8ROW_AVX2
ANY11C(Convert16To8Row_Any_AVX2,
Convert16To8Row_AVX2,
2,
1,
uint16_t,
uint8_t,
31)
#endif
#ifdef HAS_CONVERT16TO8ROW_AVX512BW
ANY11C(Convert16To8Row_Any_AVX512BW,
Convert16To8Row_AVX512BW,
2,
1,
uint16_t,
uint8_t,
63)
#endif
#ifdef HAS_CONVERT16TO8ROW_NEON
ANY11C(Convert16To8Row_Any_NEON,
Convert16To8Row_NEON,
2,
1,
uint16_t,
uint8_t,
15)
#endif
#ifdef HAS_CONVERT8TO16ROW_SSE2
ANY11C(Convert8To16Row_Any_SSE2,
Convert8To16Row_SSE2,
1,
2,
uint8_t,
uint16_t,
15)
#endif
#ifdef HAS_CONVERT8TO16ROW_AVX2
ANY11C(Convert8To16Row_Any_AVX2,
Convert8To16Row_AVX2,
1,
2,
uint8_t,
uint16_t,
31)
#endif
#ifdef HAS_CONVERT8TO16ROW_AVX512BW
ANY11C(Convert8To16Row_Any_AVX512BW,
Convert8To16Row_AVX512BW,
1,
2,
uint8_t,
uint16_t,
63)
#endif
#ifdef HAS_CONVERT8TO16ROW_NEON
ANY11C(Convert8To16Row_Any_NEON,
Convert8To16Row_NEON,
1,
2,
uint8_t,
uint16_t,
15)
#endif
#ifdef HAS_MULTIPLYROW_16_AVX512BW
ANY11C(MultiplyRow_16_Any_AVX512BW,
MultiplyRow_16_AVX512BW,
2,
2,
uint16_t,
uint16_t,
63)
#endif
#ifdef HAS_MULTIPLYROW_16_AVX2
ANY11C(MultiplyRow_16_Any_AVX2,
MultiplyRow_16_AVX2,
2,
2,
uint16_t,
uint16_t,
31)
#endif
#ifdef HAS_MULTIPLYROW_16_NEON
ANY11C(MultiplyRow_16_Any_NEON,
MultiplyRow_16_NEON,
2,
2,
uint16_t,
uint16_t,
15)
#endif
#ifdef HAS_DIVIDEROW_16_AVX2
ANY11C(DivideRow_16_Any_AVX2, DivideRow_16_AVX2, 2, 2, uint16_t, uint16_t, 31)
#endif
#ifdef HAS_DIVIDEROW_16_NEON
ANY11C(DivideRow_16_Any_NEON, DivideRow_16_NEON, 2, 2, uint16_t, uint16_t, 15)
#endif
#ifdef HAS_CONVERT8TO16ROW_WASMSIMD
ANY11C(Convert8To16Row_Any_WASMSIMD,
Convert8To16Row_WASMSIMD,
1,
2,
uint8_t,
uint16_t,
15)
#endif
#ifdef HAS_MULTIPLYROW_16_WASMSIMD
ANY11C(MultiplyRow_16_Any_WASMSIMD,
MultiplyRow_16_WASMSIMD,
2,
2,
uint16_t,
uint16_t,
15)
#endif
#undef ANY11C
// Any 1 to 1 with parameter and shorts. BPP measures in shorts.
#define ANY11SB(NAMEANY, ANY_SIMD, SBPP, BPP, STYPE, DTYPE, MASK) \
void NAMEANY(const STYPE* src_ptr, DTYPE* dst_ptr, int scale, int bias, \
int width) { \
SIMD_ALIGNED(STYPE vin[64]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(DTYPE 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, dst_ptr, scale, bias, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np, r * SBPP); \
ANY_SIMD(vin, vout, scale, bias, MASK + 1); \
memcpy(dst_ptr + np, vout, r * BPP); \
}
#ifdef HAS_CONVERT8TO8ROW_NEON
ANY11SB(Convert8To8Row_Any_NEON,
Convert8To8Row_NEON,
1,
1,
uint8_t,
uint8_t,
31)
#endif
#ifdef HAS_CONVERT8TO8ROW_AVX2
ANY11SB(Convert8To8Row_Any_AVX2,
Convert8To8Row_AVX2,
1,
1,
uint8_t,
uint8_t,
31)
#endif
#undef ANY11B
// Any 1 to 1 with parameter and shorts to byte. BPP measures in shorts.
#define ANY11P16(NAMEANY, ANY_SIMD, ST, T, SBPP, BPP, MASK) \
void NAMEANY(const ST* src_ptr, T* dst_ptr, float param, int width) { \
SIMD_ALIGNED(ST vin[32]); \
static_assert((MASK + 1) * SBPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(T vout[32]); \
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, dst_ptr, param, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np, r * SBPP); \
ANY_SIMD(vin, vout, param, MASK + 1); \
memcpy(dst_ptr + np, vout, r * BPP); \
}
#ifdef HAS_HALFFLOATROW_AVX2
ANY11P16(HalfFloatRow_Any_AVX2, HalfFloatRow_AVX2, uint16_t, uint16_t, 2, 2, 15)
#endif
#ifdef HAS_HALFFLOATROW_F16C
ANY11P16(HalfFloatRow_Any_F16C, HalfFloatRow_F16C, uint16_t, uint16_t, 2, 2, 15)
ANY11P16(HalfFloat1Row_Any_F16C,
HalfFloat1Row_F16C,
uint16_t,
uint16_t,
2,
2,
15)
#endif
#ifdef HAS_HALFFLOATROW_NEON
ANY11P16(HalfFloatRow_Any_NEON, HalfFloatRow_NEON, uint16_t, uint16_t, 2, 2, 15)
#endif
#ifdef HAS_BYTETOFLOATROW_NEON
ANY11P16(ByteToFloatRow_Any_NEON, ByteToFloatRow_NEON, uint8_t, float, 1, 4, 7)
#endif
#ifdef HAS_HALFFLOATROW_LSX
ANY11P16(HalfFloatRow_Any_LSX, HalfFloatRow_LSX, uint16_t, uint16_t, 2, 2, 7)
#endif
#ifdef HAS_HALFFLOATROW_LASX
ANY11P16(HalfFloatRow_Any_LASX, HalfFloatRow_LASX, uint16_t, uint16_t, 2, 2, 15)
#endif
#undef ANY11P16
// Any 1 to 1 with yuvconstants
#define ANY11C(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, \
const struct YuvConstants* yuvconstants, int width) { \
SIMD_ALIGNED(uint8_t vin[256]); \
static_assert(SS(MASK + 1, UVSHIFT) * SBPP <= sizeof(vin), \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256]); \
static_assert((MASK + 1) * BPP <= sizeof(vout), "vout buffer too small"); \
MSAN_MEMSET(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(src_ptr, dst_ptr, yuvconstants, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \
ANY_SIMD(vin, vout, yuvconstants, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
#if defined(HAS_YUY2TOARGBROW_SSSE3)
ANY11C(YUY2ToARGBRow_Any_SSSE3, YUY2ToARGBRow_SSSE3, 1, 4, 4, 15)
ANY11C(UYVYToARGBRow_Any_SSSE3, UYVYToARGBRow_SSSE3, 1, 4, 4, 15)
#endif
#if defined(HAS_YUY2TOARGBROW_AVX2)
ANY11C(YUY2ToARGBRow_Any_AVX2, YUY2ToARGBRow_AVX2, 1, 4, 4, 31)
ANY11C(UYVYToARGBRow_Any_AVX2, UYVYToARGBRow_AVX2, 1, 4, 4, 31)
#endif
#if defined(HAS_YUY2TOARGBROW_NEON)
ANY11C(YUY2ToARGBRow_Any_NEON, YUY2ToARGBRow_NEON, 1, 4, 4, 7)
ANY11C(UYVYToARGBRow_Any_NEON, UYVYToARGBRow_NEON, 1, 4, 4, 7)
#endif
#if defined(HAS_YUY2TOARGBROW_LSX)
ANY11C(YUY2ToARGBRow_Any_LSX, YUY2ToARGBRow_LSX, 1, 4, 4, 7)
ANY11C(UYVYToARGBRow_Any_LSX, UYVYToARGBRow_LSX, 1, 4, 4, 7)
#endif
#if defined(HAS_YUY2TOARGBROW_LASX)
ANY11C(YUY2ToARGBRow_Any_LASX, YUY2ToARGBRow_LASX, 1, 4, 4, 15)
ANY11C(UYVYToARGBRow_Any_LASX, UYVYToARGBRow_LASX, 1, 4, 4, 15)
#endif
#undef ANY11C
// Any 1 to 1 interpolate. Takes 2 rows of source via stride.
#define ANY11I(NAMEANY, ANY_SIMD, TD, TS, SBPP, BPP, MASK) \
void NAMEANY(TD* dst_ptr, const TS* src_ptr, ptrdiff_t src_stride, \
int width, int source_y_fraction) { \
SIMD_ALIGNED(TS vin[64 * 2]); \
static_assert((MASK + 1) * SBPP * sizeof(TS) <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(TD vout[64]); \
static_assert((MASK + 1) * BPP * sizeof(TD) <= 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(dst_ptr, src_ptr, src_stride, n, source_y_fraction); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * SBPP, r * SBPP * sizeof(TS)); \
if (source_y_fraction) { \
memcpy(vin + 64, src_ptr + src_stride + np * SBPP, \
r * SBPP * sizeof(TS)); \
} \
ANY_SIMD(vout, vin, 64, MASK + 1, source_y_fraction); \
memcpy(dst_ptr + np * BPP, vout, r * BPP * sizeof(TD)); \
}
#if defined(HAS_INTERPOLATEROW_AVX2)
ANY11I(InterpolateRow_Any_AVX2, InterpolateRow_AVX2, uint8_t, uint8_t, 1, 1, 31)
#endif
#ifdef HAS_INTERPOLATEROW_NEON
ANY11I(InterpolateRow_Any_NEON, InterpolateRow_NEON, uint8_t, uint8_t, 1, 1, 15)
#endif
#ifdef HAS_INTERPOLATEROW_LSX
ANY11I(InterpolateRow_Any_LSX, InterpolateRow_LSX, uint8_t, uint8_t, 1, 1, 15)
#endif
#ifdef HAS_INTERPOLATEROW_LASX
ANY11I(InterpolateRow_Any_LASX, InterpolateRow_LASX, uint8_t, uint8_t, 1, 1, 31)
#endif
#ifdef HAS_INTERPOLATEROW_16_NEON
ANY11I(InterpolateRow_16_Any_NEON,
InterpolateRow_16_NEON,
uint16_t,
uint16_t,
1,
1,
7)
#endif
#ifdef HAS_INTERPOLATEROW_16_AVX2
ANY11I(InterpolateRow_16_Any_AVX2,
InterpolateRow_16_AVX2,
uint16_t,
uint16_t,
1,
1,
15)
#endif
#ifdef HAS_INTERPOLATEROW_WASMSIMD
ANY11I(InterpolateRow_Any_WASMSIMD,
InterpolateRow_WASMSIMD,
uint8_t,
uint8_t,
1,
1,
15)
#endif
#ifdef HAS_INTERPOLATEROW_16_WASMSIMD
ANY11I(InterpolateRow_16_Any_WASMSIMD,
InterpolateRow_16_WASMSIMD,
uint16_t,
uint16_t,
1,
1,
7)
#endif
#undef ANY11I
// Any 1 to 1 half row with scale param
#define ANY11HS(NAMEANY, ANY_SIMD, TS, TD, MASK) \
void NAMEANY(const TS* src_ptr, ptrdiff_t src_stride, TD* dst_ptr, \
int scale, int width) { \
SIMD_ALIGNED(TS vin[64 * 2]); \
static_assert((MASK + 1) * sizeof(TS) <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(TD vout[64]); \
static_assert((MASK + 1) * sizeof(TD) <= 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, src_stride, dst_ptr, scale, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np, r * sizeof(TS)); \
memcpy(vin + 64, src_ptr + src_stride + np, r * sizeof(TS)); \
ANY_SIMD(vin, 64, vout, scale, MASK + 1); \
memcpy(dst_ptr + np, vout, r * sizeof(TD)); \
}
#ifdef HAS_HALFROW_16TO8_SSSE3
ANY11HS(HalfRow_16To8_Any_SSSE3, HalfRow_16To8_SSSE3, uint16_t, uint8_t, 15)
#endif
#ifdef HAS_HALFROW_16TO8_AVX2
ANY11HS(HalfRow_16To8_Any_AVX2, HalfRow_16To8_AVX2, uint16_t, uint8_t, 31)
#endif
#ifdef HAS_HALFROW_16TO8_AVX512BW
ANY11HS(HalfRow_16To8_Any_AVX512BW,
HalfRow_16To8_AVX512BW,
uint16_t,
uint8_t,
63)
#endif
#ifdef HAS_HALFROW_16TO8_NEON
ANY11HS(HalfRow_16To8_Any_NEON, HalfRow_16To8_NEON, uint16_t, uint8_t, 15)
#endif
#undef ANY11HS
// Any 2 to 1 half-width row with scale param
#define ANY11HWS(NAMEANY, ANY_SIMD, TS, TD, MASK) \
void NAMEANY(const TS* src_ptr, ptrdiff_t src_stride, TD* dst_ptr, \
int scale, int width) { \
SIMD_ALIGNED(TS vin[128 * 2]); \
static_assert((MASK + 1) * 2 * sizeof(TS) <= sizeof(vin), \
"vin buffer too small"); \
SIMD_ALIGNED(TD vout[64]); \
static_assert((MASK + 1) * sizeof(TD) <= 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, src_stride, dst_ptr, scale, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * 2, r * 2 * sizeof(TS)); \
memcpy(vin + 128, src_ptr + src_stride + np * 2, r * 2 * sizeof(TS)); \
ANY_SIMD(vin, 128, vout, scale, MASK + 1); \
memcpy(dst_ptr + np, vout, r * sizeof(TD)); \
}
#ifdef HAS_HALFWIDTHROW_16TO8_SSSE3
ANY11HWS(HalfWidthRow_16To8_Any_SSSE3,
HalfWidthRow_16To8_SSSE3,
uint16_t,
uint8_t,
7)
#endif
#ifdef HAS_HALFWIDTHROW_16TO8_AVX2
ANY11HWS(HalfWidthRow_16To8_Any_AVX2,
HalfWidthRow_16To8_AVX2,
uint16_t,
uint8_t,
15)
#endif
#ifdef HAS_HALFWIDTHROW_16TO8_AVX512BW
ANY11HWS(HalfWidthRow_16To8_Any_AVX512BW,
HalfWidthRow_16To8_AVX512BW,
uint16_t,
uint8_t,
31)
#endif
#ifdef HAS_HALFWIDTHROW_16TO8_NEON
ANY11HWS(HalfWidthRow_16To8_Any_NEON,
HalfWidthRow_16To8_NEON,
uint16_t,
uint8_t,
7)
#endif
#undef ANY11HWS
// Any 1 to 1 mirror.
#define ANY11M(NAMEANY, ANY_SIMD, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, int width) { \
SIMD_ALIGNED(uint8_t vin[128]); \
static_assert((MASK + 1) * BPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[128]); \
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 * BPP, dst_ptr, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr, r * BPP); \
ANY_SIMD(vin, vout, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout + (MASK + 1 - r) * BPP, r * BPP); \
}
#ifdef HAS_MIRRORROW_AVX512BW
ANY11M(MirrorRow_Any_AVX512BW, MirrorRow_AVX512BW, 1, 63)
#endif
#ifdef HAS_MIRRORROW_AVX2
ANY11M(MirrorRow_Any_AVX2, MirrorRow_AVX2, 1, 31)
#endif
#ifdef HAS_MIRRORROW_SSSE3
ANY11M(MirrorRow_Any_SSSE3, MirrorRow_SSSE3, 1, 15)
#endif
#ifdef HAS_MIRRORROW_NEON
ANY11M(MirrorRow_Any_NEON, MirrorRow_NEON, 1, 31)
#endif
#ifdef HAS_MIRRORROW_LSX
ANY11M(MirrorRow_Any_LSX, MirrorRow_LSX, 1, 15)
#endif
#ifdef HAS_MIRRORROW_LASX
ANY11M(MirrorRow_Any_LASX, MirrorRow_LASX, 1, 31)
#endif
#ifdef HAS_MIRRORUVROW_AVX512BW
ANY11M(MirrorUVRow_Any_AVX512BW, MirrorUVRow_AVX512BW, 2, 31)
#endif
#ifdef HAS_MIRRORUVROW_AVX2
ANY11M(MirrorUVRow_Any_AVX2, MirrorUVRow_AVX2, 2, 15)
#endif
#ifdef HAS_MIRRORUVROW_SSSE3
ANY11M(MirrorUVRow_Any_SSSE3, MirrorUVRow_SSSE3, 2, 7)
#endif
#ifdef HAS_MIRRORUVROW_NEON
ANY11M(MirrorUVRow_Any_NEON, MirrorUVRow_NEON, 2, 31)
#endif
#ifdef HAS_MIRRORUVROW_LSX
ANY11M(MirrorUVRow_Any_LSX, MirrorUVRow_LSX, 2, 7)
#endif
#ifdef HAS_MIRRORUVROW_LASX
ANY11M(MirrorUVRow_Any_LASX, MirrorUVRow_LASX, 2, 15)
#endif
#ifdef HAS_ARGBMIRRORROW_AVX2
ANY11M(ARGBMirrorRow_Any_AVX2, ARGBMirrorRow_AVX2, 4, 7)
#endif
#ifdef HAS_ARGBMIRRORROW_SSE2
ANY11M(ARGBMirrorRow_Any_SSE2, ARGBMirrorRow_SSE2, 4, 3)
#endif
#ifdef HAS_ARGBMIRRORROW_NEON
ANY11M(ARGBMirrorRow_Any_NEON, ARGBMirrorRow_NEON, 4, 7)
#endif
#ifdef HAS_ARGBMIRRORROW_LSX
ANY11M(ARGBMirrorRow_Any_LSX, ARGBMirrorRow_LSX, 4, 3)
#endif
#ifdef HAS_ARGBMIRRORROW_LASX
ANY11M(ARGBMirrorRow_Any_LASX, ARGBMirrorRow_LASX, 4, 7)
#endif
#ifdef HAS_RGB24MIRRORROW_AVX2
ANY11M(RGB24MirrorRow_Any_AVX2, RGB24MirrorRow_AVX2, 3, 31)
#endif
#ifdef HAS_RGB24MIRRORROW_SSSE3
ANY11M(RGB24MirrorRow_Any_SSSE3, RGB24MirrorRow_SSSE3, 3, 15)
#endif
#ifdef HAS_RGB24MIRRORROW_NEON
ANY11M(RGB24MirrorRow_Any_NEON, RGB24MirrorRow_NEON, 3, 15)
#endif
#ifdef HAS_MIRRORROW_WASMSIMD
ANY11M(MirrorRow_Any_WASMSIMD, MirrorRow_WASMSIMD, 1, 15)
#endif
#ifdef HAS_MIRRORUVROW_WASMSIMD
ANY11M(MirrorUVRow_Any_WASMSIMD, MirrorUVRow_WASMSIMD, 2, 7)
#endif
#ifdef HAS_ARGBMIRRORROW_WASMSIMD
ANY11M(ARGBMirrorRow_Any_WASMSIMD, ARGBMirrorRow_WASMSIMD, 4, 3)
#endif
#ifdef HAS_RGB24MIRRORROW_WASMSIMD
ANY11M(RGB24MirrorRow_Any_WASMSIMD, RGB24MirrorRow_WASMSIMD, 3, 15)
#endif
#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)
#define ANY1(NAMEANY, ANY_SIMD, T, BPP, MASK) \
void NAMEANY(uint8_t* dst_ptr, T v32, int width) { \
SIMD_ALIGNED(uint8_t vout[64]); \
static_assert((MASK + 1) * BPP <= sizeof(vout), "vout buffer too small"); \
MSAN_MEMSET(vout, 0, sizeof(vout)); /* for msan */ \
int r = width & MASK; \
int n = width & ~MASK; \
if (n > 0) { \
ANY_SIMD(dst_ptr, v32, n); \
} \
ptrdiff_t np = n; \
ANY_SIMD(vout, v32, MASK + 1); \
memcpy(dst_ptr + np * BPP, vout, r * BPP); \
}
#ifdef HAS_SETROW_X86
ANY1(SetRow_Any_X86, SetRow_X86, uint8_t, 1, 3)
#endif
#ifdef HAS_SETROW_NEON
ANY1(SetRow_Any_NEON, SetRow_NEON, uint8_t, 1, 15)
#endif
#ifdef HAS_SETROW_LSX
ANY1(SetRow_Any_LSX, SetRow_LSX, uint8_t, 1, 15)
#endif
#ifdef HAS_SETROW_LASX
ANY1(SetRow_Any_LASX, SetRow_LASX, uint8_t, 1, 31)
#endif
#ifdef HAS_ARGBSETROW_NEON
ANY1(ARGBSetRow_Any_NEON, ARGBSetRow_NEON, uint32_t, 4, 3)
#endif
#ifdef HAS_ARGBSETROW_LSX
ANY1(ARGBSetRow_Any_LSX, ARGBSetRow_LSX, uint32_t, 4, 3)
#endif
#ifdef HAS_ARGBSETROW_LASX
ANY1(ARGBSetRow_Any_LASX, ARGBSetRow_LASX, uint32_t, 4, 7)
#endif
#undef ANY1
// Any 1 to 2. Outputs UV planes.
#define ANY12(NAMEANY, ANY_SIMD, UVSHIFT, BPP, DUVSHIFT, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_u, uint8_t* dst_v, \
int width) { \
SIMD_ALIGNED(uint8_t vin[256]); \
static_assert(SS(MASK + 1, UVSHIFT) * BPP <= sizeof(vin), \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256 * 2]); \
static_assert(SS(MASK + 1, DUVSHIFT) <= sizeof(vout) / 2, \
"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, dst_u, dst_v, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \
ANY_SIMD(vin, vout, vout + 256, MASK + 1); \
memcpy(dst_u + (np >> DUVSHIFT), vout, SS(r, DUVSHIFT)); \
memcpy(dst_v + (np >> DUVSHIFT), vout + 256, SS(r, DUVSHIFT)); \
}
#ifdef HAS_SPLITUVROW_SSE2
ANY12(SplitUVRow_Any_SSE2, SplitUVRow_SSE2, 0, 2, 0, 15)
#endif
#ifdef HAS_SPLITUVROW_AVX512BW
ANY12(SplitUVRow_Any_AVX512BW, SplitUVRow_AVX512BW, 0, 2, 0, 63)
#endif
#ifdef HAS_SPLITUVROW_AVX2
ANY12(SplitUVRow_Any_AVX2, SplitUVRow_AVX2, 0, 2, 0, 31)
#endif
#ifdef HAS_SPLITUVROW_NEON
ANY12(SplitUVRow_Any_NEON, SplitUVRow_NEON, 0, 2, 0, 15)
#endif
#ifdef HAS_SPLITUVROW_LSX
ANY12(SplitUVRow_Any_LSX, SplitUVRow_LSX, 0, 2, 0, 15)
#endif
#ifdef HAS_SPLITUVROW_LASX
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)
ANY12(UYVYToUV422Row_Any_AVX2, UYVYToUV422Row_AVX2, 1, 4, 1, 31)
#endif
#ifdef HAS_YUY2TOUV422ROW_SSE2
ANY12(YUY2ToUV422Row_Any_SSE2, YUY2ToUV422Row_SSE2, 1, 4, 1, 15)
ANY12(UYVYToUV422Row_Any_SSE2, UYVYToUV422Row_SSE2, 1, 4, 1, 15)
#endif
#ifdef HAS_YUY2TOUV422ROW_NEON
ANY12(YUY2ToUV422Row_Any_NEON, YUY2ToUV422Row_NEON, 1, 4, 1, 15)
ANY12(UYVYToUV422Row_Any_NEON, UYVYToUV422Row_NEON, 1, 4, 1, 15)
#endif
#ifdef HAS_YUY2TOUV422ROW_LSX
ANY12(YUY2ToUV422Row_Any_LSX, YUY2ToUV422Row_LSX, 1, 4, 1, 15)
ANY12(UYVYToUV422Row_Any_LSX, UYVYToUV422Row_LSX, 1, 4, 1, 15)
#endif
#ifdef HAS_YUY2TOUV422ROW_LASX
ANY12(YUY2ToUV422Row_Any_LASX, YUY2ToUV422Row_LASX, 1, 4, 1, 31)
ANY12(UYVYToUV422Row_Any_LASX, UYVYToUV422Row_LASX, 1, 4, 1, 31)
#endif
#undef ANY12
// Any 2 16 bit planes with parameter to 1
#define ANY12PT(NAMEANY, ANY_SIMD, T, BPP, MASK) \
void NAMEANY(const T* src_uv, T* dst_u, T* dst_v, int depth, int width) { \
SIMD_ALIGNED(T vin[16 * 2]); \
static_assert((MASK + 1) * BPP * 2 <= sizeof(vin), \
"vin buffer too small"); \
SIMD_ALIGNED(T vout[16 * 2]); \
static_assert((MASK + 1) * BPP <= sizeof(vout) / 2, \
"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_uv, dst_u, dst_v, depth, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_uv + np * 2, r * BPP * 2); \
ANY_SIMD(vin, vout, vout + 16, depth, MASK + 1); \
memcpy(dst_u + np, vout, r * BPP); \
memcpy(dst_v + np, vout + 16, r * BPP); \
}
#ifdef HAS_SPLITUVROW_16_AVX2
ANY12PT(SplitUVRow_16_Any_AVX2, SplitUVRow_16_AVX2, uint16_t, 2, 15)
#endif
#ifdef HAS_SPLITUVROW_16_NEON
ANY12PT(SplitUVRow_16_Any_NEON, SplitUVRow_16_NEON, uint16_t, 2, 7)
#endif
#undef ANY21CT
// Any 1 to 3. Outputs RGB planes.
#define ANY13(NAMEANY, ANY_SIMD, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, \
uint8_t* dst_b, int width) { \
SIMD_ALIGNED(uint8_t vin[(MASK + 1) * BPP]); \
SIMD_ALIGNED(uint8_t vout[(MASK + 1) * 3]); \
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, dst_r, dst_g, dst_b, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * BPP, r * BPP); \
ANY_SIMD(vin, vout, vout + MASK + 1, vout + (MASK + 1) * 2, MASK + 1); \
memcpy(dst_r + np, vout, r); \
memcpy(dst_g + np, vout + MASK + 1, r); \
memcpy(dst_b + np, vout + (MASK + 1) * 2, r); \
}
#ifdef HAS_SPLITRGBROW_SSSE3
ANY13(SplitRGBRow_Any_SSSE3, SplitRGBRow_SSSE3, 3, 15)
#endif
#ifdef HAS_SPLITRGBROW_SSE41
ANY13(SplitRGBRow_Any_SSE41, SplitRGBRow_SSE41, 3, 15)
#endif
#ifdef HAS_SPLITRGBROW_AVX2
ANY13(SplitRGBRow_Any_AVX2, SplitRGBRow_AVX2, 3, 31)
#endif
#ifdef HAS_SPLITRGBROW_NEON
ANY13(SplitRGBRow_Any_NEON, SplitRGBRow_NEON, 3, 15)
#endif
#ifdef HAS_SPLITXRGBROW_SSE2
ANY13(SplitXRGBRow_Any_SSE2, SplitXRGBRow_SSE2, 4, 7)
#endif
#ifdef HAS_SPLITXRGBROW_SSSE3
ANY13(SplitXRGBRow_Any_SSSE3, SplitXRGBRow_SSSE3, 4, 7)
#endif
#ifdef HAS_SPLITXRGBROW_AVX2
ANY13(SplitXRGBRow_Any_AVX2, SplitXRGBRow_AVX2, 4, 15)
#endif
#ifdef HAS_SPLITXRGBROW_NEON
ANY13(SplitXRGBRow_Any_NEON, SplitXRGBRow_NEON, 4, 15)
#endif
// Any 1 to 4. Outputs ARGB planes.
#define ANY14(NAMEANY, ANY_SIMD, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, \
uint8_t* dst_b, uint8_t* dst_a, int width) { \
SIMD_ALIGNED(uint8_t vin[16 * 4]); \
static_assert((MASK + 1) * BPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[16 * 4]); \
static_assert(MASK + 1 <= sizeof(vout) / 4, "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, dst_r, dst_g, dst_b, dst_a, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * BPP, r * BPP); \
ANY_SIMD(vin, vout, vout + 16, vout + 32, vout + 48, MASK + 1); \
memcpy(dst_r + np, vout, r); \
memcpy(dst_g + np, vout + 16, r); \
memcpy(dst_b + np, vout + 32, r); \
memcpy(dst_a + np, vout + 48, r); \
}
#ifdef HAS_SPLITARGBROW_SSE2
ANY14(SplitARGBRow_Any_SSE2, SplitARGBRow_SSE2, 4, 7)
#endif
#ifdef HAS_SPLITARGBROW_SSSE3
ANY14(SplitARGBRow_Any_SSSE3, SplitARGBRow_SSSE3, 4, 7)
#endif
#ifdef HAS_SPLITARGBROW_AVX2
ANY14(SplitARGBRow_Any_AVX2, SplitARGBRow_AVX2, 4, 15)
#endif
#ifdef HAS_SPLITARGBROW_NEON
ANY14(SplitARGBRow_Any_NEON, SplitARGBRow_NEON, 4, 15)
#endif
// Any 1 to 2 with source stride (2 rows of source). Outputs UV planes.
// 128 byte row allows for 32 avx ARGB pixels.
#define ANY12S(NAMEANY, ANY_SIMD, UVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, int src_stride, uint8_t* dst_u, \
uint8_t* dst_v, int width) { \
SIMD_ALIGNED(uint8_t vin[256 * 2]); \
static_assert(SS(MASK + 1, UVSHIFT) * BPP <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256 * 2]); \
static_assert(SS(MASK + 1, 1) <= sizeof(vout) / 2, \
"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, src_stride, dst_u, dst_v, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \
memcpy(vin + 256, src_ptr + src_stride + (np >> UVSHIFT) * BPP, \
SS(r, UVSHIFT) * BPP); \
if ((width & 1) && UVSHIFT == 0) { /* repeat last pixel for subsample */ \
memcpy(vin + SS(r, UVSHIFT) * BPP, vin + SS(r, UVSHIFT) * BPP - BPP, \
BPP); \
memcpy(vin + 256 + SS(r, UVSHIFT) * BPP, \
vin + 256 + SS(r, UVSHIFT) * BPP - BPP, BPP); \
} \
ANY_SIMD(vin, 256, vout, vout + 256, MASK + 1); \
memcpy(dst_u + (np >> 1), vout, SS(r, 1)); \
memcpy(dst_v + (np >> 1), vout + 256, SS(r, 1)); \
}
#define ANY12M(NAMEANY, ANY_SIMD, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_u, uint8_t* dst_v, \
int width, const struct ArgbConstants* c) { \
SIMD_ALIGNED(uint8_t vin[256]); \
static_assert((MASK + 1) * BPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256 * 2]); \
static_assert(MASK + 1 <= sizeof(vout) / 2, "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, dst_u, dst_v, n, c); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * BPP, r * BPP); \
ANY_SIMD(vin, vout, vout + 256, MASK + 1, c); \
memcpy(dst_u + np, vout, r); \
memcpy(dst_v + np, vout + 256, r); \
}
#define ANY12MS(NAMEANY, ANY_SIMD, UVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, int src_stride, uint8_t* dst_u, \
uint8_t* dst_v, int width, const struct ArgbConstants* c) { \
SIMD_ALIGNED(uint8_t vin[256 * 2]); \
static_assert(SS(MASK + 1, UVSHIFT) * BPP <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256 * 2]); \
static_assert(SS(MASK + 1, 1) <= sizeof(vout) / 2, \
"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, src_stride, dst_u, dst_v, n, c); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \
memcpy(vin + 256, src_ptr + src_stride + (np >> UVSHIFT) * BPP, \
SS(r, UVSHIFT) * BPP); \
if ((width & 1) && UVSHIFT == 0) { /* repeat last pixel for subsample */ \
memcpy(vin + SS(r, UVSHIFT) * BPP, vin + SS(r, UVSHIFT) * BPP - BPP, \
BPP); \
memcpy(vin + 256 + SS(r, UVSHIFT) * BPP, \
vin + 256 + SS(r, UVSHIFT) * BPP - BPP, BPP); \
} \
ANY_SIMD(vin, 256, vout, vout + 256, MASK + 1, c); \
memcpy(dst_u + (np >> 1), vout, SS(r, 1)); \
memcpy(dst_v + (np >> 1), vout + 256, SS(r, 1)); \
}
#ifdef HAS_ARGBTOUVMATRIXROW_NEON
ANY12MS(ARGBToUVMatrixRow_Any_NEON, ARGBToUVMatrixRow_NEON, 0, 4, 15)
#endif
#ifdef HAS_ARGBTOUVMATRIXROW_NEON_I8MM
ANY12MS(ARGBToUVMatrixRow_Any_NEON_I8MM, ARGBToUVMatrixRow_NEON_I8MM, 0, 4, 15)
#endif
#ifdef HAS_RGBTOUVMATRIXROW_NEON
ANY12MS(RGBToUVMatrixRow_Any_NEON, RGBToUVMatrixRow_NEON, 0, 3, 15)
#endif
#ifdef HAS_RGB565TOUVMATRIXROW_NEON
ANY12MS(RGB565ToUVMatrixRow_Any_NEON, RGB565ToUVMatrixRow_NEON, 0, 2, 15)
#endif
#ifdef HAS_ARGB1555TOUVMATRIXROW_NEON
ANY12MS(ARGB1555ToUVMatrixRow_Any_NEON, ARGB1555ToUVMatrixRow_NEON, 0, 2, 15)
#endif
#ifdef HAS_ARGB4444TOUVMATRIXROW_NEON
ANY12MS(ARGB4444ToUVMatrixRow_Any_NEON, ARGB4444ToUVMatrixRow_NEON, 0, 2, 15)
#endif
#ifdef HAS_ARGBTOUVMATRIXROW_AVX2
ANY12MS(ARGBToUVMatrixRow_Any_AVX2, ARGBToUVMatrixRow_AVX2, 0, 4, 31)
ANY12MS(RGBToUVMatrixRow_Any_AVX2, RGBToUVMatrixRow_AVX2, 0, 3, 31)
ANY12MS(RGB565ToUVMatrixRow_Any_AVX2, RGB565ToUVMatrixRow_AVX2, 0, 2, 31)
#ifdef HAS_ARGB1555TOARGBROW_AVX2
ANY12MS(ARGB1555ToUVMatrixRow_Any_AVX2, ARGB1555ToUVMatrixRow_AVX2, 0, 2, 31)
#endif
#ifdef HAS_ARGB4444TOARGBROW_AVX2
ANY12MS(ARGB4444ToUVMatrixRow_Any_AVX2, ARGB4444ToUVMatrixRow_AVX2, 0, 2, 31)
#endif
#endif
#ifdef HAS_ARGBTOUVMATRIXROW_SSSE3
ANY12MS(ARGBToUVMatrixRow_Any_SSSE3, ARGBToUVMatrixRow_SSSE3, 0, 4, 7)
#endif
#ifdef HAS_RGBTOUVMATRIXROW_SSSE3
ANY12MS(RGBToUVMatrixRow_Any_SSSE3, RGBToUVMatrixRow_SSSE3, 0, 3, 7)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_AVX2
ANY12M(ARGBToUV444MatrixRow_Any_AVX2, ARGBToUV444MatrixRow_AVX2, 4, 31)
#endif
#ifdef HAS_RGBTOUV444MATRIXROW_AVX2
ANY12M(RGBToUV444MatrixRow_Any_AVX2, RGBToUV444MatrixRow_AVX2, 3, 31)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_AVX512BW
ANY12M(ARGBToUV444MatrixRow_Any_AVX512BW, ARGBToUV444MatrixRow_AVX512BW, 4, 63)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_AVX512VNNI
ANY12M(ARGBToUV444MatrixRow_Any_AVX512VNNI,
ARGBToUV444MatrixRow_AVX512VNNI,
4,
63)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_AVX512VNNIVBMI
ANY12M(ARGBToUV444MatrixRow_Any_AVX512VNNIVBMI,
ARGBToUV444MatrixRow_AVX512VNNIVBMI,
4,
63)
#endif
#ifdef HAS_RGBTOUV444MATRIXROW_AVX512BW
ANY12M(RGBToUV444MatrixRow_Any_AVX512BW, RGBToUV444MatrixRow_AVX512BW, 3, 63)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_SSSE3
ANY12M(ARGBToUV444MatrixRow_Any_SSSE3, ARGBToUV444MatrixRow_SSSE3, 4, 15)
#endif
#ifdef HAS_RGBTOUV444MATRIXROW_SSSE3
ANY12M(RGBToUV444MatrixRow_Any_SSSE3, RGBToUV444MatrixRow_SSSE3, 3, 15)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_NEON
ANY12M(ARGBToUV444MatrixRow_Any_NEON, ARGBToUV444MatrixRow_NEON, 4, 7)
#endif
#ifdef HAS_RGBTOUV444MATRIXROW_NEON
ANY12M(RGBToUV444MatrixRow_Any_NEON, RGBToUV444MatrixRow_NEON, 3, 7)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_NEON_I8MM
ANY12M(ARGBToUV444MatrixRow_Any_NEON_I8MM, ARGBToUV444MatrixRow_NEON_I8MM, 4, 7)
#endif
#ifdef HAS_ARGBTOUVMATRIXROW_WASMSIMD
ANY12MS(ARGBToUVMatrixRow_Any_WASMSIMD, ARGBToUVMatrixRow_WASMSIMD, 0, 4, 15)
#endif
#ifdef HAS_RGBTOUVMATRIXROW_WASMSIMD
ANY12MS(RGBToUVMatrixRow_Any_WASMSIMD, RGBToUVMatrixRow_WASMSIMD, 0, 3, 15)
#endif
#ifdef HAS_RGB565TOUVMATRIXROW_WASMSIMD
ANY12MS(RGB565ToUVMatrixRow_Any_WASMSIMD,
RGB565ToUVMatrixRow_WASMSIMD,
0,
2,
15)
#endif
#ifdef HAS_ARGB1555TOUVMATRIXROW_WASMSIMD
ANY12MS(ARGB1555ToUVMatrixRow_Any_WASMSIMD,
ARGB1555ToUVMatrixRow_WASMSIMD,
0,
2,
15)
#endif
#ifdef HAS_ARGB4444TOUVMATRIXROW_WASMSIMD
ANY12MS(ARGB4444ToUVMatrixRow_Any_WASMSIMD,
ARGB4444ToUVMatrixRow_WASMSIMD,
0,
2,
15)
#endif
#ifdef HAS_ARGBTOUV444MATRIXROW_WASMSIMD
ANY12M(ARGBToUV444MatrixRow_Any_WASMSIMD, ARGBToUV444MatrixRow_WASMSIMD, 4, 15)
#endif
#ifdef HAS_RGBTOUV444MATRIXROW_WASMSIMD
ANY12M(RGBToUV444MatrixRow_Any_WASMSIMD, RGBToUV444MatrixRow_WASMSIMD, 3, 15)
#endif
#define ANY11MC(NAMEANY, ANY_SIMD, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, int width, \
const struct ArgbConstants* c) { \
SIMD_ALIGNED(uint8_t vin[256]); \
static_assert((MASK + 1) * BPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[256]); \
static_assert(MASK + 1 <= 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, dst_ptr, n, c); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + np * BPP, r * BPP); \
ANY_SIMD(vin, vout, MASK + 1, c); \
memcpy(dst_ptr + np, vout, r); \
}
#ifdef HAS_ARGBTOYMATRIXROW_SSSE3
ANY11MC(ARGBToYMatrixRow_Any_SSSE3, ARGBToYMatrixRow_SSSE3, 4, 15)
ANY11MC(RGBToYMatrixRow_Any_SSSE3, RGBToYMatrixRow_SSSE3, 3, 15)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_AVX2
ANY11MC(ARGBToYMatrixRow_Any_AVX2, ARGBToYMatrixRow_AVX2, 4, 31)
ANY11MC(RGBToYMatrixRow_Any_AVX2, RGBToYMatrixRow_AVX2, 3, 31)
ANY11MC(RGB565ToYMatrixRow_Any_AVX2, RGB565ToYMatrixRow_AVX2, 2, 31)
#ifdef HAS_ARGB1555TOYMATRIXROW_AVX2
ANY11MC(ARGB1555ToYMatrixRow_Any_AVX2, ARGB1555ToYMatrixRow_AVX2, 2, 31)
#endif
#ifdef HAS_ARGB4444TOYMATRIXROW_AVX2
ANY11MC(ARGB4444ToYMatrixRow_Any_AVX2, ARGB4444ToYMatrixRow_AVX2, 2, 31)
#endif
#endif
#ifdef HAS_ARGBTOYMATRIXROW_AVX512BW
ANY11MC(ARGBToYMatrixRow_Any_AVX512BW, ARGBToYMatrixRow_AVX512BW, 4, 63)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_AVX512VNNI
ANY11MC(ARGBToYMatrixRow_Any_AVX512VNNI, ARGBToYMatrixRow_AVX512VNNI, 4, 63)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_AVX512VNNIVBMI
ANY11MC(ARGBToYMatrixRow_Any_AVX512VNNIVBMI,
ARGBToYMatrixRow_AVX512VNNIVBMI,
4,
63)
#endif
#ifdef HAS_RGBTOYMATRIXROW_AVX512BW
ANY11MC(RGBToYMatrixRow_Any_AVX512BW, RGBToYMatrixRow_AVX512BW, 3, 63)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_NEON
ANY11MC(ARGBToYMatrixRow_Any_NEON, ARGBToYMatrixRow_NEON, 4, 15)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_NEON_DOTPROD
ANY11MC(ARGBToYMatrixRow_Any_NEON_DotProd, ARGBToYMatrixRow_NEON_DotProd, 4, 15)
ANY11MC(RGBToYMatrixRow_Any_NEON_DotProd, RGBToYMatrixRow_NEON_DotProd, 3, 15)
#endif
#ifdef HAS_RGBTOYMATRIXROW_NEON
ANY11MC(RGBToYMatrixRow_Any_NEON, RGBToYMatrixRow_NEON, 3, 15)
#endif
#ifdef HAS_RGB565TOYMATRIXROW_NEON
ANY11MC(RGB565ToYMatrixRow_Any_NEON, RGB565ToYMatrixRow_NEON, 2, 15)
#endif
#ifdef HAS_ARGB1555TOYMATRIXROW_NEON
ANY11MC(ARGB1555ToYMatrixRow_Any_NEON, ARGB1555ToYMatrixRow_NEON, 2, 15)
#endif
#ifdef HAS_ARGB4444TOYMATRIXROW_NEON
ANY11MC(ARGB4444ToYMatrixRow_Any_NEON, ARGB4444ToYMatrixRow_NEON, 2, 15)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_LSX
ANY11MC(ARGBToYMatrixRow_Any_LSX, ARGBToYMatrixRow_LSX, 4, 7)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_LASX
ANY11MC(ARGBToYMatrixRow_Any_LASX, ARGBToYMatrixRow_LASX, 4, 15)
#endif
#ifdef HAS_RGBTOYMATRIXROW_LSX
ANY11MC(RGBToYMatrixRow_Any_LSX, RGBToYMatrixRow_LSX, 3, 15)
#endif
#ifdef HAS_RGBTOYMATRIXROW_LASX
ANY11MC(RGBToYMatrixRow_Any_LASX, RGBToYMatrixRow_LASX, 3, 31)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_RVV
ANY11MC(ARGBToYMatrixRow_Any_RVV, ARGBToYMatrixRow_RVV, 4, 15)
#endif
#ifdef HAS_ARGBTOYMATRIXROW_WASMSIMD
ANY11MC(ARGBToYMatrixRow_Any_WASMSIMD, ARGBToYMatrixRow_WASMSIMD, 4, 15)
#endif
#ifdef HAS_RGBTOYMATRIXROW_WASMSIMD
ANY11MC(RGBToYMatrixRow_Any_WASMSIMD, RGBToYMatrixRow_WASMSIMD, 3, 15)
#endif
#ifdef HAS_RGB565TOYMATRIXROW_WASMSIMD
ANY11MC(RGB565ToYMatrixRow_Any_WASMSIMD, RGB565ToYMatrixRow_WASMSIMD, 2, 15)
#endif
#ifdef HAS_ARGB1555TOYMATRIXROW_WASMSIMD
ANY11MC(ARGB1555ToYMatrixRow_Any_WASMSIMD, ARGB1555ToYMatrixRow_WASMSIMD, 2, 15)
#endif
#ifdef HAS_ARGB4444TOYMATRIXROW_WASMSIMD
ANY11MC(ARGB4444ToYMatrixRow_Any_WASMSIMD, ARGB4444ToYMatrixRow_WASMSIMD, 2, 15)
#endif
#undef ANY11MC
#ifdef HAS_YUY2TOUVROW_AVX2
ANY12S(YUY2ToUVRow_Any_AVX2, YUY2ToUVRow_AVX2, 1, 4, 31)
ANY12S(UYVYToUVRow_Any_AVX2, UYVYToUVRow_AVX2, 1, 4, 31)
#endif
#ifdef HAS_YUY2TOUVROW_SSE2
ANY12S(YUY2ToUVRow_Any_SSE2, YUY2ToUVRow_SSE2, 1, 4, 15)
ANY12S(UYVYToUVRow_Any_SSE2, UYVYToUVRow_SSE2, 1, 4, 15)
#endif
#ifdef HAS_RGB24TOUVROW_NEON
ANY12S(RGB24ToUVRow_Any_NEON, RGB24ToUVRow_NEON, 0, 3, 15)
#endif
#ifdef HAS_RGB24TOUVROW_LSX
ANY12S(RGB24ToUVRow_Any_LSX, RGB24ToUVRow_LSX, 0, 3, 15)
#endif
#ifdef HAS_RGB24TOUVROW_LASX
ANY12S(RGB24ToUVRow_Any_LASX, RGB24ToUVRow_LASX, 0, 3, 31)
#endif
#ifdef HAS_RAWTOUVROW_NEON
ANY12S(RAWToUVRow_Any_NEON, RAWToUVRow_NEON, 0, 3, 15)
#endif
#ifdef HAS_RAWTOUVROW_LSX
ANY12S(RAWToUVRow_Any_LSX, RAWToUVRow_LSX, 0, 3, 15)
#endif
#ifdef HAS_RAWTOUVROW_LASX
ANY12S(RAWToUVRow_Any_LASX, RAWToUVRow_LASX, 0, 3, 31)
#endif
#ifdef HAS_RGB565TOUVROW_NEON
ANY12S(RGB565ToUVRow_Any_NEON, RGB565ToUVRow_NEON, 0, 2, 15)
#endif
#ifdef HAS_RGB565TOUVROW_LSX
ANY12S(RGB565ToUVRow_Any_LSX, RGB565ToUVRow_LSX, 0, 2, 15)
#endif
#ifdef HAS_RGB565TOUVROW_LASX
ANY12S(RGB565ToUVRow_Any_LASX, RGB565ToUVRow_LASX, 0, 2, 31)
#endif
#ifdef HAS_ARGB1555TOUVROW_NEON
ANY12S(ARGB1555ToUVRow_Any_NEON, ARGB1555ToUVRow_NEON, 0, 2, 15)
#endif
#ifdef HAS_ARGB1555TOUVROW_LSX
ANY12S(ARGB1555ToUVRow_Any_LSX, ARGB1555ToUVRow_LSX, 0, 2, 15)
#endif
#ifdef HAS_ARGB1555TOUVROW_LASX
ANY12S(ARGB1555ToUVRow_Any_LASX, ARGB1555ToUVRow_LASX, 0, 2, 31)
#endif
#ifdef HAS_ARGB4444TOUVROW_NEON
ANY12S(ARGB4444ToUVRow_Any_NEON, ARGB4444ToUVRow_NEON, 0, 2, 15)
#endif
#ifdef HAS_YUY2TOUVROW_NEON
ANY12S(YUY2ToUVRow_Any_NEON, YUY2ToUVRow_NEON, 1, 4, 15)
#endif
#ifdef HAS_UYVYTOUVROW_NEON
ANY12S(UYVYToUVRow_Any_NEON, UYVYToUVRow_NEON, 1, 4, 15)
#endif
#ifdef HAS_YUY2TOUVROW_LSX
ANY12S(YUY2ToUVRow_Any_LSX, YUY2ToUVRow_LSX, 1, 4, 15)
#endif
#ifdef HAS_YUY2TOUVROW_LASX
ANY12S(YUY2ToUVRow_Any_LASX, YUY2ToUVRow_LASX, 1, 4, 31)
#endif
#ifdef HAS_UYVYTOUVROW_LSX
ANY12S(UYVYToUVRow_Any_LSX, UYVYToUVRow_LSX, 1, 4, 15)
#endif
#ifdef HAS_UYVYTOUVROW_LASX
ANY12S(UYVYToUVRow_Any_LASX, UYVYToUVRow_LASX, 1, 4, 31)
#endif
#undef ANY12S
// Any 1 to 1 with source stride (2 rows of source). Outputs UV plane.
// 128 byte row allows for 32 avx ARGB pixels.
#define ANY11S(NAMEANY, ANY_SIMD, UVSHIFT, BPP, MASK) \
void NAMEANY(const uint8_t* src_ptr, int src_stride, uint8_t* dst_vu, \
int width) { \
SIMD_ALIGNED(uint8_t vin[128 * 2]); \
static_assert(SS(MASK + 1, UVSHIFT) * BPP <= sizeof(vin) / 2, \
"vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[128]); \
static_assert(SS(MASK + 1, 1) * 2 <= 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, src_stride, dst_vu, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_ptr + (np >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \
memcpy(vin + 128, src_ptr + src_stride + (np >> UVSHIFT) * BPP, \
SS(r, UVSHIFT) * BPP); \
if ((width & 1) && UVSHIFT == 0) { /* repeat last pixel for subsample */ \
memcpy(vin + SS(r, UVSHIFT) * BPP, vin + SS(r, UVSHIFT) * BPP - BPP, \
BPP); \
memcpy(vin + 128 + SS(r, UVSHIFT) * BPP, \
vin + 128 + SS(r, UVSHIFT) * BPP - BPP, BPP); \
} \
ANY_SIMD(vin, 128, vout, MASK + 1); \
memcpy(dst_vu + (np >> 1) * 2, vout, SS(r, 1) * 2); \
}
#ifdef HAS_AYUVTOVUROW_NEON
ANY11S(AYUVToUVRow_Any_NEON, AYUVToUVRow_NEON, 0, 4, 15)
ANY11S(AYUVToVURow_Any_NEON, AYUVToVURow_NEON, 0, 4, 15)
#endif
#ifdef HAS_AYUVTOUVROW_SVE2
ANY11S(AYUVToUVRow_Any_SVE2, AYUVToUVRow_SVE2, 0, 4, 1)
#endif
#ifdef HAS_AYUVTOVUROW_SVE2
ANY11S(AYUVToVURow_Any_SVE2, AYUVToVURow_SVE2, 0, 4, 1)
#endif
#undef ANY11S
#define ANYDETILE(NAMEANY, ANY_SIMD, T, BPP, MASK) \
void NAMEANY(const T* src, ptrdiff_t src_tile_stride, T* dst, int width) { \
SIMD_ALIGNED(T vin[16]); \
static_assert((MASK + 1) * BPP <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(T vout[16]); \
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, src_tile_stride, dst, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src + (np / 16) * src_tile_stride, r * BPP); \
ANY_SIMD(vin, src_tile_stride, vout, MASK + 1); \
memcpy(dst + np, vout, r * BPP); \
}
#ifdef HAS_DETILEROW_NEON
ANYDETILE(DetileRow_Any_NEON, DetileRow_NEON, uint8_t, 1, 15)
#endif
#ifdef HAS_DETILEROW_SSE2
ANYDETILE(DetileRow_Any_SSE2, DetileRow_SSE2, uint8_t, 1, 15)
#endif
#ifdef HAS_DETILEROW_16_NEON
ANYDETILE(DetileRow_16_Any_NEON, DetileRow_16_NEON, uint16_t, 2, 15)
#endif
#ifdef HAS_DETILEROW_16_SSE2
ANYDETILE(DetileRow_16_Any_SSE2, DetileRow_16_SSE2, uint16_t, 2, 15)
#endif
#ifdef HAS_DETILEROW_16_AVX
ANYDETILE(DetileRow_16_Any_AVX, DetileRow_16_AVX, uint16_t, 2, 15)
#endif
// DetileSplitUVRow width is in bytes
#define ANYDETILESPLITUV(NAMEANY, ANY_SIMD, MASK) \
void NAMEANY(const uint8_t* src_uv, ptrdiff_t src_tile_stride, \
uint8_t* dst_u, uint8_t* dst_v, int width) { \
SIMD_ALIGNED(uint8_t vin[16]); \
static_assert(MASK + 1 <= sizeof(vin), "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[8 * 2]); \
static_assert((MASK + 1) / 2 <= sizeof(vout) / 2, \
"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_uv, src_tile_stride, dst_u, dst_v, n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_uv + (np / 16) * src_tile_stride, r); \
ANY_SIMD(vin, src_tile_stride, vout, vout + 8, r); \
memcpy(dst_u + np / 2, vout, (r + 1) / 2); \
memcpy(dst_v + np / 2, vout + 8, (r + 1) / 2); \
}
#ifdef HAS_DETILESPLITUVROW_NEON
ANYDETILESPLITUV(DetileSplitUVRow_Any_NEON, DetileSplitUVRow_NEON, 15)
#endif
#ifdef HAS_DETILESPLITUVROW_SSSE3
ANYDETILESPLITUV(DetileSplitUVRow_Any_SSSE3, DetileSplitUVRow_SSSE3, 15)
#endif
#define ANYDETILEMERGE(NAMEANY, ANY_SIMD, MASK) \
void NAMEANY(const uint8_t* src_y, ptrdiff_t src_y_tile_stride, \
const uint8_t* src_uv, ptrdiff_t src_uv_tile_stride, \
uint8_t* dst_yuy2, int width) { \
SIMD_ALIGNED(uint8_t vin[16 * 2]); \
static_assert(MASK + 1 <= sizeof(vin) / 2, "vin buffer too small"); \
SIMD_ALIGNED(uint8_t vout[16 * 2]); \
static_assert(2 * (MASK + 1) <= 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_y, src_y_tile_stride, src_uv, src_uv_tile_stride, dst_yuy2, \
n); \
} \
ptrdiff_t np = n; \
memcpy(vin, src_y + (np / 16) * src_y_tile_stride, r); \
memcpy(vin + 16, src_uv + (np / 16) * src_uv_tile_stride, r); \
ANY_SIMD(vin, src_y_tile_stride, vin + 16, src_uv_tile_stride, vout, r); \
memcpy(dst_yuy2 + 2 * np, vout, 2 * r); \
}
#ifdef HAS_DETILETOYUY2_NEON
ANYDETILEMERGE(DetileToYUY2_Any_NEON, DetileToYUY2_NEON, 15)
#endif
#ifdef HAS_DETILETOYUY2_SSE2
ANYDETILEMERGE(DetileToYUY2_Any_SSE2, DetileToYUY2_SSE2, 15)
#endif
#undef MSAN_MEMSET
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
#endif