[libyuv] Fix top 9 bugs and performance issues

1. Fix TestCpuFlag(A | B) multi-bit checks in AYUVToNV12, AYUVToNV21,
   NV12ToRGB24Matrix, RAWToRGBARow, MergeRGBRow, and MergeXR30Row so
   that all required ISA flags are verified (== (A | B)) instead of
   matching when only one flag is present.
2. Fix 2-byte heap buffer overflow on odd widths in
   I422ToARGB1555Row_SVE_SC and I422ToARGB4444Row_SVE_SC by replacing
   st1h on interleaved lanes with trn1/trn2 + st2b under per-pixel byte
   predicates.
3. Fix ARGBPolynomialRow_SSE2 clamping outputs to <= 127 (packssdw
   before packuswb instead of double packuswb) and add missing
   vzeroupper to SplitRGBRow_AVX2.
4. Fix AR64ShuffleRow_C processing only half the row (loop bound width
   instead of width / 2).
5. Fix negative-height crashes and orientation errors in
   ConvertFromI420, SplitARGBPlane (when dst_a == NULL), I422Rotate,
   I010Rotate, and I210Rotate.
6. Fix signed 16.16 fixed-point coordinate handling for negative x/dx
   in ScaleFilterCols_NEON (asr + 64-bit sign-extended x64/dx64) and
   ScaleAddCols1_16_C (x >>= 16).
7. Fix ConvertToARGB odd crop_x UV alignment for NV12/NV21, src_u
   offset calculation on odd sample widths for I420/YV12/J420/H420/U420,
   and FOURCC_U422 BT.2020 matrix dispatch (U422ToARGB).
8. Remove dead 14-instruction block before loop label 1: in
   ScaleRowUp2_Bilinear_16_SSE2.
9. Fix SIMD feature macros, dead dispatches, and SVE2 loop tail
   branches:
   - Define HAS_SCALECOLSUP2_SSE2 in scale.cc for 32-bit x86.
   - Guard TransposeWx4_32_SVE2 in rotate_argb.cc with
     HAS_TRANSPOSEWX4_32_SVE2.
   - Restrict HAS_UYVYTOARGBROW_SME and HAS_SCALEUVROWDOWN2_SME to
     Clang >= 20 to match their implementations.
   - Add AB64ToARGBRow_Any_NEON/SSE2/AVX2/AVX512BW wrappers so unaligned
     widths use SIMD + C tail.
   - Remove duplicate macro definitions in include/libyuv/row.h.
   - Replace b.lt 2f / b.ge 1b with b.gt 1b in SVE2 row loops so one
     redundant tail iteration is not executed when width % vl == 0.

R=rrwinterton@gmail.com

Bug: libyuv:574714081, b/574714081
Test: out/Release/libyuv_unittest && out/asan/libyuv_unittest
Change-Id: Iec3ae5c58d52bee3ef13cf9b765ac84b733aa576
This commit is contained in:
Frank Barchard 2026-10-16 22:54:16 -07:00
parent 2404f9730e
commit d2ad07b483
17 changed files with 99 additions and 91 deletions

View File

@ -153,13 +153,11 @@ extern "C" {
#define HAS_ARGBCOPYALPHAROW_AVX2
#define HAS_ARGBCOPYYTOALPHAROW_AVX2
#define HAS_ARGBEXTRACTALPHAROW_AVX2
#define HAS_ARGBMIRRORROW_AVX2
#define HAS_ARGBPOLYNOMIALROW_AVX2
#define HAS_ARGBSHUFFLEROW_AVX2
#define HAS_ARGBTORGB565DITHERROW_AVX2
#define HAS_COPYROW_AVX
#define HAS_HALFFLOATROW_AVX2
#define HAS_I422TOARGBROW_AVX2
#define HAS_I422TORGB24ROW_AVX2
#define HAS_I422TORGBAROW_AVX2
#define HAS_I422TORGB565ROW_AVX2
@ -168,12 +166,8 @@ extern "C" {
#define HAS_I444TOARGBROW_AVX2
#define HAS_I444TORGB24ROW_AVX2
#define HAS_J400TOARGBROW_AVX2
#define HAS_MIRRORROW_AVX2
#define HAS_MIRRORSPLITUVROW_AVX2
#define HAS_NV12TOARGBROW_AVX2
#define HAS_NV12TORGB24ROW_AVX2
#define HAS_NV12TORGB565ROW_AVX2
#define HAS_NV21TOARGBROW_AVX2
#define HAS_NV21TORGB24ROW_AVX2
#define HAS_SPLITUVROW_AVX2
#define HAS_UYVYTOARGBROW_AVX2
@ -474,7 +468,6 @@ extern "C" {
#define HAS_RGBTOUV444MATRIXROW_AVX512BW
#define HAS_ARGBTOYMATRIXROW_AVX512BW
#define HAS_I422TORGB24ROW_AVX512VBMI
#define HAS_RAWTORGB24ROW_AVX512VBMI
#define HAS_I422TORGB24ROW_AVX512BW
#define HAS_ARGBTOUVMATRIXROW_AVX512BW
#define HAS_J400TOARGBROW_AVX512BW
@ -796,6 +789,7 @@ extern "C" {
#define HAS_P210TOARGBROW_SME
#define HAS_P410TOAR30ROW_SME
#define HAS_P410TOARGBROW_SME
#define HAS_UYVYTOARGBROW_SME
#define HAS_YUY2TOARGBROW_SME
#endif

View File

@ -466,7 +466,7 @@ static inline void I400ToARGBRow_SVE_SC(const uint8_t* src_y,
"ptrue p0.b \n"
"dup z19.b, #255 \n" // Alpha
YUVTORGB_SVE_SETUP
"cmp %w[width], %w[vl] \n"
"subs %w[width], %w[width], %w[vl] \n"
"mov z1.h, #128 \n" // U/V
"umullb z6.h, z30.b, z1.b \n"
"umullb z4.h, z28.b, z1.b \n" // DB
@ -475,25 +475,28 @@ static inline void I400ToARGBRow_SVE_SC(const uint8_t* src_y,
"sub z4.h, z4.h, z25.h \n"
"sub z5.h, z5.h, z27.h \n"
"sub z6.h, z26.h, z6.h \n"
"b.le 2f \n"
"b.lt 2f \n"
// Run bulk of computation with an all-true predicate to avoid predicate
// generation overhead.
"ptrue p1.h \n"
"sub %w[width], %w[width], %w[vl] \n"
"1: \n" //
READYUV400_SVE I400TORGB_SVE RGBTOARGB8_SVE
"subs %w[width], %w[width], %w[vl] \n"
"st2h {z16.h, z17.h}, p1, [%[dst_argb]] \n"
"add %[dst_argb], %[dst_argb], %[vl], lsl #2 \n"
"b.gt 1b \n"
"add %w[width], %w[width], %w[vl] \n"
"b.ge 1b \n"
"2: \n"
"adds %w[width], %w[width], %w[vl] \n"
"b.eq 99f \n"
// Calculate a predicate for the final iteration to deal with the tail.
"2: \n"
"whilelt p1.h, wzr, %w[width] \n" //
READYUV400_SVE I400TORGB_SVE RGBTOARGB8_SVE
"st2h {z16.h, z17.h}, p1, [%[dst_argb]] \n"
"99: \n"
: [src_y] "+r"(src_y), // %[src_y]
[dst_argb] "+r"(dst_argb), // %[dst_argb]
[width] "+r"(width), // %[width]
@ -702,7 +705,11 @@ static inline void I422ToARGB1555Row_SVE_SC(
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X
RGBTOARGB8_SVE_TOP_2X RGB8TOARGB1555_SVE_FROM_TOP_2X
"st2h {z0.h, z1.h}, p1, [%[dst]] \n"
// Need to permute the data on the final iteration such that the
// predicates (.b) line up with the 16-bit element data.
"trn1 z2.b, z0.b, z1.b \n"
"trn2 z3.b, z0.b, z1.b \n"
"st2b {z2.b, z3.b}, p1, [%[dst]] \n"
"99: \n"
: [src_y] "+r"(src_y), // %[src_y]
@ -761,7 +768,11 @@ static inline void I422ToARGB4444Row_SVE_SC(
"whilelt p1.b, wzr, %w[width] \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X
RGBTOARGB8_SVE_TOP_2X RGB8TOARGB4444_SVE_FROM_TOP_2X
"st2h {z0.h, z1.h}, p1, [%[dst]] \n"
// Need to permute the data on the final iteration such that the
// predicates (.b) line up with the 16-bit element data.
"trn1 z2.b, z0.b, z1.b \n"
"trn2 z3.b, z0.b, z1.b \n"
"st2b {z2.b, z3.b}, p1, [%[dst]] \n"
"99: \n"
: [src_y] "+r"(src_y), // %[src_y]
@ -788,7 +799,7 @@ static inline void I422ToRGBARow_SVE_SC(const uint8_t* src_y,
YUVTORGB_SVE_SETUP
"dup z19.b, #255 \n" // Alpha
"subs %w[width], %w[width], %w[vl] \n"
"b.le 2f \n"
"b.lt 2f \n"
// Run bulk of computation with an all-true predicate to avoid predicate
// generation overhead.
@ -798,7 +809,7 @@ static inline void I422ToRGBARow_SVE_SC(const uint8_t* src_y,
"subs %w[width], %w[width], %w[vl] \n"
"st2h {z19.h, z20.h}, p1, [%[dst_rgba]] \n"
"add %[dst_rgba], %[dst_rgba], %[vl], lsl #2 \n"
"b.gt 1b \n"
"b.ge 1b \n"
// Calculate a predicate for the final iteration to deal with the tail.
"2: \n"
@ -836,7 +847,7 @@ static inline void I422ToAR30Row_SVE_SC(const uint8_t* src_y,
YUVTORGB_SVE_SETUP_AR30
"dup z23.h, %w[limit] \n"
"subs %w[width], %w[width], %w[vl], lsl #1 \n"
"b.le 2f \n"
"b.lt 2f \n"
// Run bulk of computation with an all-true predicate to avoid predicate
// generation overhead.
@ -846,7 +857,7 @@ static inline void I422ToAR30Row_SVE_SC(const uint8_t* src_y,
"1: \n" //
READYUV422_SVE_2X I422TORGB_SVE_2X STOREAR30_SVE_2X
"subs %w[width], %w[width], %w[vl], lsl #1 \n"
"b.gt 1b \n"
"b.ge 1b \n"
// Calculate a predicate for the final iteration to deal with the tail.
"2: \n"
@ -2120,7 +2131,7 @@ static inline void ARGBToUVMatrixRow_SVE_SC(const uint8_t* src_argb,
"ptrue p5.h \n"
"1: \n" //
ARGBTOUVMATRIX_SVE
"b.gt 1b \n"
"b.ge 1b \n"
"2: \n"
"adds %w[width], %w[width], %w[vl], lsl #2 \n"
@ -2197,7 +2208,7 @@ static inline void ARGBToYMatrixRow_SVE_SC(const uint8_t* src_argb,
"ptrue p1.s \n"
"1: \n" //
ARGBTOYMATRIX_SVE("p1", "p1", "p1", "p1", "p0")
"b.gt 1b \n"
"b.ge 1b \n"
"2: \n"
"adds %w[width], %w[width], %w[vl], lsl #2 \n"

View File

@ -2669,7 +2669,8 @@ int AYUVToNV12(const uint8_t* src_ayuv,
}
#endif
#if defined(HAS_AYUVTOYROW_AVX512VBMI)
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL) ==
(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
AYUVToUVRow = AYUVToUVRow_AVX512VBMI;
AYUVToYRow = AYUVToYRow_AVX512VBMI;
}
@ -2755,7 +2756,8 @@ int AYUVToNV21(const uint8_t* src_ayuv,
}
#endif
#if defined(HAS_AYUVTOYROW_AVX512VBMI)
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL) ==
(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
AYUVToVURow = AYUVToVURow_AVX512VBMI;
AYUVToYRow = AYUVToYRow_AVX512VBMI;
}

View File

@ -4133,7 +4133,8 @@ int RAWToRGBA(const uint8_t* src_raw,
}
#endif
#if defined(HAS_RAWTORGBAROW_AVX512VBMI)
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL) ==
(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
RAWToRGBARow = RAWToRGBARow_AVX512VBMI;
}
#endif
@ -4990,7 +4991,8 @@ int NV12ToRGB24Matrix(const uint8_t* src_y,
}
#endif
#if defined(HAS_NV12TORGB24ROW_AVX512VBMI)
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL) ==
(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
NV12ToRGB24Row = NV12ToRGB24Row_AVX512VBMI;
}
#endif
@ -5072,7 +5074,8 @@ int NV21ToRGB24Matrix(const uint8_t* src_y,
}
#endif
#if defined(HAS_NV21TORGB24ROW_AVX512VBMI)
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL) ==
(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
NV21ToRGB24Row = NV21ToRGB24Row_AVX512VBMI;
}
#endif

View File

@ -1028,6 +1028,7 @@ int ConvertFromI420(const uint8_t* y,
height == INT_MIN) {
return -1;
}
const int abs_height = Abs(height);
switch (format) {
// Single plane formats
case FOURCC_YUY2:
@ -1097,7 +1098,7 @@ int ConvertFromI420(const uint8_t* y,
break;
case FOURCC_NV12: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * height;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
r = I420ToNV12(y, y_stride, u, u_stride, v, v_stride, dst_sample,
dst_sample_stride ? dst_sample_stride : width, dst_uv,
dst_sample_stride ? dst_sample_stride : width, width,
@ -1106,7 +1107,7 @@ int ConvertFromI420(const uint8_t* y,
}
case FOURCC_NV21: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
uint8_t* dst_vu = dst_sample + (ptrdiff_t)dst_y_stride * height;
uint8_t* dst_vu = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
r = I420ToNV21(y, y_stride, u, u_stride, v, v_stride, dst_sample,
dst_sample_stride ? dst_sample_stride : width, dst_vu,
dst_sample_stride ? dst_sample_stride : width, width,
@ -1116,13 +1117,13 @@ int ConvertFromI420(const uint8_t* y,
case FOURCC_NV16: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
int dst_uv_stride = dst_sample_stride ? dst_sample_stride : width;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * height;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
int halfwidth = (width + 1) / 2;
int halfheight = (height + 1) / 2;
int halfheight = SUBSAMPLE(height, 1, 1);
CopyPlane(y, y_stride, dst_sample, dst_y_stride, width, height);
MergeUVPlane(u, u_stride, v, v_stride, dst_uv, dst_uv_stride * 2,
halfwidth, halfheight);
if (height > 1) {
if (abs_height > 1) {
MergeUVPlane(u, u_stride, v, v_stride, dst_uv + dst_uv_stride,
dst_uv_stride * 2, halfwidth, height / 2);
}
@ -1132,9 +1133,9 @@ int ConvertFromI420(const uint8_t* y,
case FOURCC_NV24: {
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
int dst_uv_stride = dst_sample_stride ? dst_sample_stride * 2 : width * 2;
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * height;
align_buffer_64(temp_u, (size_t)width * height);
align_buffer_64(temp_v, (size_t)width * height);
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * abs_height;
align_buffer_64(temp_u, (size_t)width * abs_height);
align_buffer_64(temp_v, (size_t)width * abs_height);
if (!temp_u || !temp_v) {
free_aligned_buffer_64(temp_u);
free_aligned_buffer_64(temp_v);
@ -1144,7 +1145,7 @@ int ConvertFromI420(const uint8_t* y,
dst_y_stride, temp_u, width, temp_v, width, width, height);
if (r == 0) {
MergeUVPlane(temp_u, width, temp_v, width, dst_uv, dst_uv_stride, width,
height);
abs_height);
}
free_aligned_buffer_64(temp_u);
free_aligned_buffer_64(temp_v);
@ -1152,7 +1153,6 @@ int ConvertFromI420(const uint8_t* y,
}
case FOURCC_P010:
case FOURCC_P210: {
const int abs_height = Abs(height);
const int uv_min = ((width + 1) / 2) * 2;
int dst_stride_y;
int dst_stride_uv;
@ -1183,7 +1183,6 @@ int ConvertFromI420(const uint8_t* y,
break;
}
case FOURCC_P410: {
const int abs_height = Abs(height);
const int uv_min = width * 2;
int dst_stride_y;
int dst_stride_uv;
@ -1213,14 +1212,14 @@ int ConvertFromI420(const uint8_t* y,
case FOURCC_YV12: {
dst_sample_stride = dst_sample_stride ? dst_sample_stride : width;
int halfstride = (dst_sample_stride + 1) / 2;
int halfheight = (height + 1) / 2;
int halfheight = (abs_height + 1) / 2;
uint8_t* dst_u;
uint8_t* dst_v;
if (format == FOURCC_YV12) {
dst_v = dst_sample + (ptrdiff_t)dst_sample_stride * height;
dst_v = dst_sample + (ptrdiff_t)dst_sample_stride * abs_height;
dst_u = dst_v + (ptrdiff_t)halfstride * halfheight;
} else {
dst_u = dst_sample + (ptrdiff_t)dst_sample_stride * height;
dst_u = dst_sample + (ptrdiff_t)dst_sample_stride * abs_height;
dst_v = dst_u + (ptrdiff_t)halfstride * halfheight;
}
r = I420Copy(y, y_stride, u, u_stride, v, v_stride, dst_sample,
@ -1235,11 +1234,11 @@ int ConvertFromI420(const uint8_t* y,
uint8_t* dst_u;
uint8_t* dst_v;
if (format == FOURCC_YV16) {
dst_v = dst_sample + (ptrdiff_t)dst_sample_stride * height;
dst_u = dst_v + (ptrdiff_t)halfstride * height;
dst_v = dst_sample + (ptrdiff_t)dst_sample_stride * abs_height;
dst_u = dst_v + (ptrdiff_t)halfstride * abs_height;
} else {
dst_u = dst_sample + (ptrdiff_t)dst_sample_stride * height;
dst_v = dst_u + (ptrdiff_t)halfstride * height;
dst_u = dst_sample + (ptrdiff_t)dst_sample_stride * abs_height;
dst_v = dst_u + (ptrdiff_t)halfstride * abs_height;
}
r = I420ToI422(y, y_stride, u, u_stride, v, v_stride, dst_sample,
dst_sample_stride, dst_u, halfstride, dst_v, halfstride,
@ -1252,11 +1251,11 @@ int ConvertFromI420(const uint8_t* y,
uint8_t* dst_u;
uint8_t* dst_v;
if (format == FOURCC_YV24) {
dst_v = dst_sample + (ptrdiff_t)dst_sample_stride * height;
dst_u = dst_v + (ptrdiff_t)dst_sample_stride * height;
dst_v = dst_sample + (ptrdiff_t)dst_sample_stride * abs_height;
dst_u = dst_v + (ptrdiff_t)dst_sample_stride * abs_height;
} else {
dst_u = dst_sample + (ptrdiff_t)dst_sample_stride * height;
dst_v = dst_u + (ptrdiff_t)dst_sample_stride * height;
dst_u = dst_sample + (ptrdiff_t)dst_sample_stride * abs_height;
dst_v = dst_u + (ptrdiff_t)dst_sample_stride * abs_height;
}
r = I420ToI444(y, y_stride, u, u_stride, v, v_stride, dst_sample,
dst_sample_stride, dst_u, dst_sample_stride, dst_v,

View File

@ -433,7 +433,7 @@ int ConvertToARGB(const uint8_t* sample,
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample +
aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y / 2) +
crop_x;
(crop_x & ~1);
r = NV12ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
dst_stride_argb, crop_width, inv_crop_height);
break;
@ -441,7 +441,7 @@ int ConvertToARGB(const uint8_t* sample,
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
src_uv = sample +
aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y / 2) +
crop_x;
(crop_x & ~1);
// Call NV12 but with u and v parameters swapped.
r = NV21ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
dst_stride_argb, crop_width, inv_crop_height);
@ -508,12 +508,12 @@ int ConvertToARGB(const uint8_t* sample,
int halfheight = (abs_src_height + 1) / 2;
if (format == FOURCC_YV12) {
src_v = sample + (ptrdiff_t)src_width * abs_src_height +
((ptrdiff_t)halfwidth * crop_y + crop_x) / 2;
(ptrdiff_t)halfwidth * (crop_y / 2) + crop_x / 2;
src_u = sample + (ptrdiff_t)src_width * abs_src_height +
halfwidth * ((ptrdiff_t)halfheight + crop_y / 2) + crop_x / 2;
} else {
src_u = sample + (ptrdiff_t)src_width * abs_src_height +
((ptrdiff_t)halfwidth * crop_y + crop_x) / 2;
(ptrdiff_t)halfwidth * (crop_y / 2) + crop_x / 2;
src_v = sample + (ptrdiff_t)src_width * abs_src_height +
halfwidth * ((ptrdiff_t)halfheight + crop_y / 2) + crop_x / 2;
}
@ -527,7 +527,7 @@ int ConvertToARGB(const uint8_t* sample,
int halfheight = (abs_src_height + 1) / 2;
const uint8_t* src_y = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
const uint8_t* src_u = sample + (ptrdiff_t)src_width * abs_src_height +
((ptrdiff_t)halfwidth * crop_y + crop_x) / 2;
(ptrdiff_t)halfwidth * (crop_y / 2) + crop_x / 2;
const uint8_t* src_v = sample + (ptrdiff_t)src_width * abs_src_height +
halfwidth * ((ptrdiff_t)halfheight + crop_y / 2) +
crop_x / 2;
@ -541,7 +541,7 @@ int ConvertToARGB(const uint8_t* sample,
int halfheight = (abs_src_height + 1) / 2;
const uint8_t* src_y = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
const uint8_t* src_u = sample + (ptrdiff_t)src_width * abs_src_height +
((ptrdiff_t)halfwidth * crop_y + crop_x) / 2;
(ptrdiff_t)halfwidth * (crop_y / 2) + crop_x / 2;
const uint8_t* src_v = sample + (ptrdiff_t)src_width * abs_src_height +
halfwidth * ((ptrdiff_t)halfheight + crop_y / 2) +
crop_x / 2;
@ -555,7 +555,7 @@ int ConvertToARGB(const uint8_t* sample,
int halfheight = (abs_src_height + 1) / 2;
const uint8_t* src_y = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
const uint8_t* src_u = sample + (ptrdiff_t)src_width * abs_src_height +
((ptrdiff_t)halfwidth * crop_y + crop_x) / 2;
(ptrdiff_t)halfwidth * (crop_y / 2) + crop_x / 2;
const uint8_t* src_v = sample + (ptrdiff_t)src_width * abs_src_height +
halfwidth * ((ptrdiff_t)halfheight + crop_y / 2) +
crop_x / 2;
@ -620,7 +620,7 @@ int ConvertToARGB(const uint8_t* sample,
const uint8_t* src_v = sample + (ptrdiff_t)src_width * abs_src_height +
halfwidth * ((ptrdiff_t)abs_src_height + crop_y) +
crop_x / 2;
r = H422ToARGB(src_y, src_width, src_u, halfwidth, src_v, halfwidth,
r = U422ToARGB(src_y, src_width, src_u, halfwidth, src_v, halfwidth,
dst_argb, dst_stride_argb, crop_width, inv_crop_height);
break;
}

View File

@ -1595,7 +1595,8 @@ void MergeRGBPlane(const uint8_t* src_r,
}
#endif
#if defined(HAS_MERGERGBROW_AVX512VBMI)
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
if (TestCpuFlag(kCpuHasAVX512VBMI | kCpuHasAVX512VL) ==
(kCpuHasAVX512VBMI | kCpuHasAVX512VL)) {
MergeRGBRow = MergeRGBRow_AVX512VBMI;
}
#endif
@ -1799,11 +1800,13 @@ void SplitARGBPlane(const uint8_t* src_argb,
dst_r = dst_r + (ptrdiff_t)(height - 1) * dst_stride_r;
dst_g = dst_g + (ptrdiff_t)(height - 1) * dst_stride_g;
dst_b = dst_b + (ptrdiff_t)(height - 1) * dst_stride_b;
dst_a = dst_a + (ptrdiff_t)(height - 1) * dst_stride_a;
dst_stride_r = -dst_stride_r;
dst_stride_g = -dst_stride_g;
dst_stride_b = -dst_stride_b;
dst_stride_a = -dst_stride_a;
if (dst_a) {
dst_a = dst_a + (ptrdiff_t)(height - 1) * dst_stride_a;
dst_stride_a = -dst_stride_a;
}
}
if (dst_a == NULL) {
@ -2030,7 +2033,8 @@ void MergeXR30Plane(const uint16_t* src_r,
}
#endif
#if defined(HAS_MERGEXR30ROW_10_AVX512BW)
if (depth == 10 && TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL)) {
if (depth == 10 && TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
(kCpuHasAVX512BW | kCpuHasAVX512VL)) {
MergeXR30Row = MergeXR30Row_10_AVX512BW;
}
#endif

View File

@ -927,6 +927,7 @@ int I422Rotate(const uint8_t* src_y,
// Negative height means invert the image.
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v;
@ -1234,9 +1235,10 @@ int I010Rotate(const uint16_t* src_y,
// Negative height means invert the image.
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v;
src_u = src_u + (ptrdiff_t)(halfheight - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(halfheight - 1) * src_stride_v;
src_stride_y = -src_stride_y;
src_stride_u = -src_stride_u;
src_stride_v = -src_stride_v;
@ -1305,6 +1307,7 @@ int I210Rotate(const uint16_t* src_y,
// Negative height means invert the image.
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
src_u = src_u + (ptrdiff_t)(height - 1) * src_stride_u;
src_v = src_v + (ptrdiff_t)(height - 1) * src_stride_v;

View File

@ -78,6 +78,9 @@ static int ARGBTranspose(const uint8_t* src_argb,
#if defined(HAS_TRANSPOSEWX4_32_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
TransposeWx4_32 = TransposeWx4_32_SVE2;
#if defined(HAS_TRANSPOSEWXH_32_NEON)
TransposeWxH_32 = NULL;
#endif
}
#endif
#if defined(HAS_TRANSPOSEWXH_32_SME)

View File

@ -1575,7 +1575,7 @@ ANY11T(ARGBToAB64Row_Any_SSSE3, ARGBToAB64Row_SSSE3, 4, 8, uint8_t, uint16_t, 3)
ANY11T(AR64ToARGBRow_Any_SSSE3, AR64ToARGBRow_SSSE3, 8, 4, uint16_t, uint8_t, 3)
#endif
#ifdef HAS_ARGBTOAR64ROW_SSSE3
#ifdef HAS_AB64TOARGBROW_SSSE3
ANY11T(AB64ToARGBRow_Any_SSSE3, AB64ToARGBRow_SSSE3, 8, 4, uint16_t, uint8_t, 3)
#endif
@ -1591,7 +1591,7 @@ ANY11T(ARGBToAB64Row_Any_AVX2, ARGBToAB64Row_AVX2, 4, 8, uint8_t, uint16_t, 7)
ANY11T(AR64ToARGBRow_Any_AVX2, AR64ToARGBRow_AVX2, 8, 4, uint16_t, uint8_t, 7)
#endif
#ifdef HAS_ARGBTOAR64ROW_AVX2
#ifdef HAS_AB64TOARGBROW_AVX2
ANY11T(AB64ToARGBRow_Any_AVX2, AB64ToARGBRow_AVX2, 8, 4, uint16_t, uint8_t, 7)
#endif
@ -1607,7 +1607,7 @@ ANY11T(ARGBToAB64Row_Any_NEON, ARGBToAB64Row_NEON, 4, 8, uint8_t, uint16_t, 7)
ANY11T(AR64ToARGBRow_Any_NEON, AR64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
#endif
#ifdef HAS_ARGBTOAR64ROW_NEON
#ifdef HAS_AB64TOARGBROW_NEON
ANY11T(AB64ToARGBRow_Any_NEON, AB64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
#endif

View File

@ -595,7 +595,7 @@ void AR64ShuffleRow_C(const uint8_t* src_ar64,
int index3 = shuffler[6] / 2;
// Shuffle a row of AR64.
int x;
for (x = 0; x < width / 2; ++x) {
for (x = 0; x < width; ++x) {
// To support in-place conversion.
uint16_t b = src_ar64_16[index0];
uint16_t g = src_ar64_16[index1];

View File

@ -7056,6 +7056,7 @@ void SplitRGBRow_AVX2(const uint8_t* src_rgb,
"lea 0x20(%3),%3 \n"
"sub $0x20,%4 \n"
"jg 1b \n"
"vzeroupper \n"
: "+r"(src_rgb), // %0
"+r"(dst_r), // %1
"+r"(dst_g), // %2
@ -11102,7 +11103,7 @@ void ARGBPolynomialRow_SSE2(const uint8_t* src_argb,
"addps %%xmm5,%%xmm4 \n"
"cvttps2dq %%xmm0,%%xmm0 \n"
"cvttps2dq %%xmm4,%%xmm4 \n"
"packuswb %%xmm4,%%xmm0 \n"
"packssdw %%xmm4,%%xmm0 \n"
"packuswb %%xmm0,%%xmm0 \n"
"movq %%xmm0,(%1) \n"
"lea 0x8(%1),%1 \n"

View File

@ -777,7 +777,7 @@ void DivideRow_16_SVE2(const uint16_t* src_y,
"cnth %x[vl] \n"
"dup z0.h, %w[scale] \n"
"subs %w[width], %w[width], %w[vl], lsl #1 \n"
"b.le 2f \n"
"b.lt 2f \n"
// Run bulk of computation with the same predicates to avoid predicate
// generation overhead.
@ -792,7 +792,7 @@ void DivideRow_16_SVE2(const uint16_t* src_y,
"st1h {z1.h}, p0, [%[dst]] \n"
"st1h {z2.h}, p0, [%[dst], #1, mul vl] \n"
"incb %[dst], all, mul #2 \n"
"b.gt 1b \n"
"b.ge 1b \n"
"2: \n"
"adds %w[width], %w[width], %w[vl], lsl #1 \n"
@ -1221,7 +1221,7 @@ void CopyRow_SVE2(const uint8_t* src, uint8_t* dst, int width) {
"st1b {z0.b}, p0, [%[dst], #0, mul vl] \n"
"st1b {z1.b}, p0, [%[dst], #1, mul vl] \n"
"incb %[dst], all, mul #2 \n"
"b.gt 1b \n"
"b.ge 1b \n"
"2: \n"
"adds %w[width], %w[width], %w[vl2] \n"

View File

@ -917,6 +917,7 @@ static void ScaleAddCols1_16_C(int dst_width,
int boxwidth = MIN1(dx >> 16);
int scaleval = 65536 / (boxwidth * boxheight);
int i;
x >>= 16;
for (i = 0; i < dst_width; ++i) {
*dst_ptr++ = SumPixels_16(boxwidth, src_ptr + x) * scaleval >> 16;
x += boxwidth;
@ -1449,7 +1450,7 @@ static int ScalePlaneBilinearUp(int src_width,
#endif
if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
ScaleFilterCols = ScaleColsUp2_C;
#if defined(HAS_SCALECOLS_SSE2)
#if defined(HAS_SCALECOLSUP2_SSE2)
if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
ScaleFilterCols = ScaleColsUp2_SSE2;
}
@ -2038,7 +2039,7 @@ static void ScalePlaneSimple(int src_width,
if (src_width * 2 == dst_width && x < 0x8000) {
ScaleCols = ScaleColsUp2_C;
#if defined(HAS_SCALECOLS_SSE2)
#if defined(HAS_SCALECOLSUP2_SSE2)
if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
ScaleCols = ScaleColsUp2_SSE2;
}

View File

@ -1275,21 +1275,6 @@ void ScaleRowUp2_Bilinear_16_SSE2(const uint16_t* src_ptr,
LABELALIGN
"1: \n"
"movq (%0),%%xmm0 \n" // 0011 (16b, 1u1v)
"movq 4(%0),%%xmm1 \n" // 1122 (16b, 1u1v)
"punpcklwd %%xmm7,%%xmm0 \n" // 0011 (near) (32b, 1u1v)
"punpcklwd %%xmm7,%%xmm1 \n" // 1122 (near) (32b, 1u1v)
"movdqa %%xmm0,%%xmm2 \n"
"movdqa %%xmm1,%%xmm3 \n"
"pshufd $0b01001110,%%xmm2,%%xmm2 \n" // 1100 (far) (1, lo)
"pshufd $0b01001110,%%xmm3,%%xmm3 \n" // 2211 (far) (1, hi)
"paddd %%xmm0,%%xmm2 \n" // near+far (1, lo)
"paddd %%xmm1,%%xmm3 \n" // near+far (1, hi)
"paddd %%xmm0,%%xmm0 \n" // 2*near (1, lo)
"paddd %%xmm1,%%xmm1 \n" // 2*near (1, hi)
"paddd %%xmm2,%%xmm0 \n" // 3*near+far (1, lo)
"paddd %%xmm3,%%xmm1 \n" // 3*near+far (1, hi)
"movq (%0),%%xmm0 \n" // 0123 (16b)
"movq 2(%0),%%xmm1 \n" // 1234 (16b)
"punpcklwd %%xmm7,%%xmm0 \n" // 0123 (32b)

View File

@ -1013,7 +1013,7 @@ void ScaleAddRow_NEON(const uint8_t* src_ptr,
}
#define SCALE_FILTER_COLS_STEP_ADDR \
"lsr %[tmp_offset], %x[x], #16 \n" \
"asr %[tmp_offset], %x[x], #16 \n" \
"add %[tmp_ptr], %[src_ptr], %[tmp_offset] \n" \
"add %x[x], %x[x], %x[dx] \n"
@ -1027,6 +1027,8 @@ void ScaleFilterCols_NEON(uint8_t* dst_ptr,
int x,
int dx) {
int dx_offset[4] = {0, 1, 2, 3};
int64_t x64 = (int64_t)x;
int64_t dx64 = (int64_t)dx;
int64_t tmp_offset;
uint8_t* tmp_ptr;
asm volatile(
@ -1080,8 +1082,8 @@ void ScaleFilterCols_NEON(uint8_t* dst_ptr,
: [src_ptr] "+r"(src_ptr), // %[src_ptr]
[dst_ptr] "+r"(dst_ptr), // %[dst_ptr]
[width] "+r"(dst_width), // %[width]
[x] "+r"(x), // %[x]
[dx] "+r"(dx), // %[dx]
[x] "+r"(x64), // %[x]
[dx] "+r"(dx64), // %[dx]
[tmp_offset] "=&r"(tmp_offset), // %[tmp_offset]
[tmp_ptr] "=&r"(tmp_ptr) // %[tmp_ptr]
: [dx_offset] "r"(dx_offset) // %[dx_offset]

View File

@ -226,7 +226,7 @@ static int ScaleUVDown4Box(int src_width,
}
}
#endif
#if defined(HAS_SCALEUVROWDOWN2BOX_SME)
#if defined(HAS_SCALEUVROWDOWN2_SME)
if (TestCpuFlag(kCpuHasSME)) {
ScaleUVRowDown2 = ScaleUVRowDown2Box_SME;
}