Make 2 step transitive tests measure 2 step time.

Add tests of all macros used by libyuv public headers

When a 1 step conversion is added, a 2 step test can compare
the old 2 step method to the 1 step.  A 1 step unittest is
also added which compares C to SIMD.  Making the 2 step
conversions measure performance of the 2 steps allows the
old 2 step performance to be compared to 1 step.

All macros used in public headers are added to an ifdef test.
Showing them in a unittest allows some diagnostics when
a test is failing.

Bug: libyuv:901
Change-Id: I7ffa6ed0cb3b506fa1b7fd4b7b1b729658c3c266
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2857916
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: Mirko Bonadei <mbonadei@chromium.org>
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
Frank Barchard 2021-04-30 09:54:44 -07:00 committed by Frank Barchard
parent 99cddd8051
commit 49ebc996aa
18 changed files with 430 additions and 366 deletions

View File

@ -1,6 +1,6 @@
Name: libyuv Name: libyuv
URL: http://code.google.com/p/libyuv/ URL: http://code.google.com/p/libyuv/
Version: 1787 Version: 1788
License: BSD License: BSD
License File: LICENSE License File: LICENSE

View File

@ -18,7 +18,7 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
#if defined(__pnacl__) || defined(__CLR_VER) || \ #if defined(__pnacl__) || defined(__CLR_VER) || \
(defined(__native_client__) && defined(__x86_64__)) || \ (defined(__native_client__) && defined(__x86_64__)) || \
(defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) (defined(__i386__) && !defined(__SSE__) && !defined(__clang__))
#define LIBYUV_DISABLE_X86 #define LIBYUV_DISABLE_X86
@ -54,16 +54,15 @@ extern "C" {
#endif #endif
// The following are available for Visual C and clangcl 32 bit: // The following are available for Visual C and clangcl 32 bit:
#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && \ #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) && \
defined(_MSC_VER) && !defined(__clang__) && \ !defined(__clang__) && \
(defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2))
#define HAS_HASHDJB2_AVX2 #define HAS_HASHDJB2_AVX2
#define HAS_SUMSQUAREERROR_AVX2 #define HAS_SUMSQUAREERROR_AVX2
#endif #endif
// The following are available for GCC and clangcl: // The following are available for GCC and clangcl:
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
#define HAS_HAMMINGDISTANCE_SSSE3 #define HAS_HAMMINGDISTANCE_SSSE3
#endif #endif

View File

@ -23,7 +23,7 @@ extern "C" {
#endif #endif
// TODO(fbarchard): Move cpu macros to row.h // TODO(fbarchard): Move cpu macros to row.h
#if defined(__pnacl__) || defined(__CLR_VER) || \ #if defined(__pnacl__) || defined(__CLR_VER) || \
(defined(__native_client__) && defined(__x86_64__)) || \ (defined(__native_client__) && defined(__x86_64__)) || \
(defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) (defined(__i386__) && !defined(__SSE__) && !defined(__clang__))
#define LIBYUV_DISABLE_X86 #define LIBYUV_DISABLE_X86

View File

@ -18,7 +18,7 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
#if defined(__pnacl__) || defined(__CLR_VER) || \ #if defined(__pnacl__) || defined(__CLR_VER) || \
(defined(__native_client__) && defined(__x86_64__)) || \ (defined(__native_client__) && defined(__x86_64__)) || \
(defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) (defined(__i386__) && !defined(__SSE__) && !defined(__clang__))
#define LIBYUV_DISABLE_X86 #define LIBYUV_DISABLE_X86

View File

@ -20,7 +20,7 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
#if defined(__pnacl__) || defined(__CLR_VER) || \ #if defined(__pnacl__) || defined(__CLR_VER) || \
(defined(__native_client__) && defined(__x86_64__)) || \ (defined(__native_client__) && defined(__x86_64__)) || \
(defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) (defined(__i386__) && !defined(__SSE__) && !defined(__clang__))
#define LIBYUV_DISABLE_X86 #define LIBYUV_DISABLE_X86
@ -269,8 +269,7 @@ extern "C" {
// The following are available for gcc/clang x86 platforms: // The following are available for gcc/clang x86 platforms:
// TODO(fbarchard): Port to Visual C // TODO(fbarchard): Port to Visual C
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
#define HAS_ABGRTOAR30ROW_SSSE3 #define HAS_ABGRTOAR30ROW_SSSE3
#define HAS_ARGBTOAR30ROW_SSSE3 #define HAS_ARGBTOAR30ROW_SSSE3
#define HAS_ARGBTOAR64ROW_SSSE3 #define HAS_ARGBTOAR64ROW_SSSE3
@ -316,7 +315,7 @@ extern "C" {
// The following are available for AVX2 gcc/clang x86 platforms: // The following are available for AVX2 gcc/clang x86 platforms:
// TODO(fbarchard): Port to Visual C // TODO(fbarchard): Port to Visual C
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && \
(defined(__x86_64__) || defined(__i386__)) && \ (defined(__x86_64__) || defined(__i386__)) && \
(defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) (defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2))
#define HAS_ABGRTOAR30ROW_AVX2 #define HAS_ABGRTOAR30ROW_AVX2
@ -376,9 +375,8 @@ extern "C" {
// The following are available for AVX512 clang x86 platforms: // The following are available for AVX512 clang x86 platforms:
// TODO(fbarchard): Port to GCC and Visual C // TODO(fbarchard): Port to GCC and Visual C
// TODO(fbarchard): re-enable HAS_ARGBTORGB24ROW_AVX512VBMI. Issue libyuv:789 // TODO(fbarchard): re-enable HAS_ARGBTORGB24ROW_AVX512VBMI. Issue libyuv:789
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && \
(defined(__x86_64__) || defined(__i386__)) && \ (defined(__x86_64__) || defined(__i386__)) && (defined(CLANG_HAS_AVX512))
(defined(CLANG_HAS_AVX512))
#define HAS_ARGBTORGB24ROW_AVX512VBMI #define HAS_ARGBTORGB24ROW_AVX512VBMI
#endif #endif

View File

@ -19,7 +19,7 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
#if defined(__pnacl__) || defined(__CLR_VER) || \ #if defined(__pnacl__) || defined(__CLR_VER) || \
(defined(__native_client__) && defined(__x86_64__)) || \ (defined(__native_client__) && defined(__x86_64__)) || \
(defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) (defined(__i386__) && !defined(__SSE__) && !defined(__clang__))
#define LIBYUV_DISABLE_X86 #define LIBYUV_DISABLE_X86
@ -74,8 +74,7 @@ extern "C" {
// The following are available for gcc/clang x86 platforms: // The following are available for gcc/clang x86 platforms:
// TODO(fbarchard): Port to Visual C // TODO(fbarchard): Port to Visual C
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
#define HAS_SCALEUVROWDOWN2BOX_SSSE3 #define HAS_SCALEUVROWDOWN2BOX_SSSE3
#define HAS_SCALEROWUP2LINEAR_SSE2 #define HAS_SCALEROWUP2LINEAR_SSE2
#define HAS_SCALEROWUP2LINEAR_SSSE3 #define HAS_SCALEROWUP2LINEAR_SSSE3
@ -94,8 +93,8 @@ extern "C" {
// The following are available for gcc/clang x86 platforms, but // The following are available for gcc/clang x86 platforms, but
// require clang 3.4 or gcc 4.7. // require clang 3.4 or gcc 4.7.
// TODO(fbarchard): Port to Visual C // TODO(fbarchard): Port to Visual C
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && \
(defined(__x86_64__) || defined(__i386__)) && \ (defined(__x86_64__) || defined(__i386__)) && \
(defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) (defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2))
#define HAS_SCALEUVROWDOWN2BOX_AVX2 #define HAS_SCALEUVROWDOWN2BOX_AVX2
#define HAS_SCALEROWUP2LINEAR_AVX2 #define HAS_SCALEROWUP2LINEAR_AVX2

View File

@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ #ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1787 #define LIBYUV_VERSION 1788
#endif // INCLUDE_LIBYUV_VERSION_H_ #endif // INCLUDE_LIBYUV_VERSION_H_

View File

@ -19,8 +19,7 @@ extern "C" {
#endif #endif
// This module is for GCC x86 and x64. // This module is for GCC x86 and x64.
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
#if defined(__x86_64__) #if defined(__x86_64__)
uint32_t HammingDistance_SSE42(const uint8_t* src_a, uint32_t HammingDistance_SSE42(const uint8_t* src_a,

View File

@ -17,8 +17,7 @@ extern "C" {
#endif #endif
// This module is for GCC x86 and x64. // This module is for GCC x86 and x64.
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
// Transpose 8x8. 32 or 64 bit, but not NaCL for 64 bit. // Transpose 8x8. 32 or 64 bit, but not NaCL for 64 bit.
#if defined(HAS_TRANSPOSEWX8_SSSE3) #if defined(HAS_TRANSPOSEWX8_SSSE3)

View File

@ -1634,12 +1634,12 @@ MAKEYUVCONSTANTS(V2020, YG, YB, UB, UG, VG, VR)
int g16 = y1 + bg - (u * ug + v * vg); \ int g16 = y1 + bg - (u * ug + v * vg); \
int r16 = y1 + (v * vr) - br int r16 = y1 + (v * vr) - br
#else #else
#define LOAD_YUV_CONSTANTS \ #define LOAD_YUV_CONSTANTS \
int ub = yuvconstants->kUVToB[0]; \ int ub = yuvconstants->kUVToB[0]; \
int ug = yuvconstants->kUVToG[0]; \ int ug = yuvconstants->kUVToG[0]; \
int vg = yuvconstants->kUVToG[1]; \ int vg = yuvconstants->kUVToG[1]; \
int vr = yuvconstants->kUVToR[1]; \ int vr = yuvconstants->kUVToR[1]; \
int yg = yuvconstants->kYToRgb[0]; \ int yg = yuvconstants->kYToRgb[0]; \
int yb = yuvconstants->kYBiasToRgb[0] int yb = yuvconstants->kYBiasToRgb[0]
#define CALC_RGB16 \ #define CALC_RGB16 \

View File

@ -16,8 +16,7 @@ extern "C" {
#endif #endif
// This module is for GCC x86 and x64. // This module is for GCC x86 and x64.
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3) #if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3)
@ -2770,7 +2769,7 @@ void OMITFP I210AlphaToARGBRow_SSSE3(const uint16_t* y_buf,
int width) { int width) {
asm volatile( asm volatile(
YUVTORGB_SETUP( YUVTORGB_SETUP(
yuvconstants) "sub %[u_buf],%[v_buf] \n" yuvconstants) "sub %[u_buf],%[v_buf] \n"
LABELALIGN "1: \n" READYUVA210 LABELALIGN "1: \n" READYUVA210
YUVTORGB(yuvconstants) STOREARGB YUVTORGB(yuvconstants) STOREARGB
@ -3376,8 +3375,7 @@ void OMITFP I422ToRGBARow_SSSE3(const uint8_t* y_buf,
"vpsubsw %%ymm1,%%ymm4,%%ymm1 \n" \ "vpsubsw %%ymm1,%%ymm4,%%ymm1 \n" \
"vpaddsw %%ymm4,%%ymm2,%%ymm2 \n" "vpaddsw %%ymm4,%%ymm2,%%ymm2 \n"
#define YUVTORGB_REGS_AVX2 \ #define YUVTORGB_REGS_AVX2 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13",
#else // Convert 16 pixels: 16 UV and 16 Y. #else // Convert 16 pixels: 16 UV and 16 Y.

View File

@ -241,7 +241,7 @@ void I422ToRGBARow_NEON(const uint8_t* src_y,
YUVTORGB_SETUP YUVTORGB_SETUP
"vmov.u8 d6, #255 \n" "vmov.u8 d6, #255 \n"
"1: \n" READYUV422 YUVTORGB "1: \n" READYUV422 YUVTORGB
RGBTORGB8 "subs %[width], %[width], #8 \n" STORERGBA RGBTORGB8 "subs %[width], %[width], #8 \n" STORERGBA
"bgt 1b \n" "bgt 1b \n"
: [src_y] "+r"(src_y), // %[src_y] : [src_y] "+r"(src_y), // %[src_y]
[src_u] "+r"(src_u), // %[src_u] [src_u] "+r"(src_u), // %[src_u]
@ -294,7 +294,7 @@ void I422ToRGB565Row_NEON(const uint8_t* src_y,
YUVTORGB_SETUP YUVTORGB_SETUP
"vmov.u8 d6, #255 \n" "vmov.u8 d6, #255 \n"
"1: \n" READYUV422 YUVTORGB "1: \n" READYUV422 YUVTORGB
RGBTORGB8 "subs %[width], %[width], #8 \n" ARGBTORGB565 RGBTORGB8 "subs %[width], %[width], #8 \n" ARGBTORGB565
"vst1.8 {q2}, [%[dst_rgb565]]! \n" // store 8 pixels RGB565. "vst1.8 {q2}, [%[dst_rgb565]]! \n" // store 8 pixels RGB565.
"bgt 1b \n" "bgt 1b \n"
: [src_y] "+r"(src_y), // %[src_y] : [src_y] "+r"(src_y), // %[src_y]

View File

@ -277,7 +277,7 @@ void I422ToRGB565Row_NEON(const uint8_t* src_y,
asm volatile( asm volatile(
YUVTORGB_SETUP YUVTORGB_SETUP
"1: \n" READYUV422 YUVTORGB "1: \n" READYUV422 YUVTORGB
RGBTORGB8 "subs %w[width], %w[width], #8 \n" ARGBTORGB565 RGBTORGB8 "subs %w[width], %w[width], #8 \n" ARGBTORGB565
"st1 {v18.8h}, [%[dst_rgb565]], #16 \n" // store 8 pixels RGB565. "st1 {v18.8h}, [%[dst_rgb565]], #16 \n" // store 8 pixels RGB565.
"b.gt 1b \n" "b.gt 1b \n"
: [src_y] "+r"(src_y), // %[src_y] : [src_y] "+r"(src_y), // %[src_y]

File diff suppressed because it is too large Load Diff

View File

@ -17,8 +17,7 @@ extern "C" {
#endif #endif
// This module is for GCC x86 and x64. // This module is for GCC x86 and x64.
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
// Offsets for source bytes 0 to 9 // Offsets for source bytes 0 to 9
static const uvec8 kShuf0 = {0, 1, 3, 4, 5, 7, 8, 9, static const uvec8 kShuf0 = {0, 1, 3, 4, 5, 7, 8, 9,

View File

@ -22,8 +22,7 @@ namespace libyuv {
// TODO(fbarchard): clang x86 has a higher accuracy YUV to RGB. // TODO(fbarchard): clang x86 has a higher accuracy YUV to RGB.
// Port to Visual C and other CPUs // Port to Visual C and other CPUs
#if !defined(LIBYUV_DISABLE_X86) && \ #if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
(defined(__x86_64__) || defined(__i386__))
#define ERROR_FULL 5 #define ERROR_FULL 5
#define ERROR_J420 4 #define ERROR_J420 4
#else #else

View File

@ -183,7 +183,7 @@ TESTPLANARTOP(I412, uint16_t, 2, 1, 1, I444, uint8_t, 1, 1, 1, 12)
#define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, \ #define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, \
SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
W1280, N, NEG, OFF, PN, OFF_U, OFF_V) \ W1280, N, NEG, OFF, PN, OFF_U, OFF_V) \
TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##_##PN##N) { \ TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##To##PN##N) { \
const int kWidth = W1280; \ const int kWidth = W1280; \
const int kHeight = benchmark_height_; \ const int kHeight = benchmark_height_; \
const int kSizeUV = \ const int kSizeUV = \
@ -2817,10 +2817,11 @@ TESTPTOB(TestYUY2ToNV12, YUY2ToI420, YUY2ToNV12)
TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12) TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
// Transitive tests. A to B to C is same as A to C. // Transitive tests. A to B to C is same as A to C.
// Benchmarks A To B to C for comparison to 1 step, benchmarked elsewhere.
#define TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \ #define TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
W1280, N, NEG, OFF, FMT_C, BPP_C) \ W1280, N, NEG, OFF, FMT_C, BPP_C) \
TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) { \ TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##To##FMT_C##N) { \
const int kWidth = W1280; \ const int kWidth = W1280; \
const int kHeight = benchmark_height_; \ const int kHeight = benchmark_height_; \
const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \ const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \
@ -2838,23 +2839,23 @@ TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
src_v[i + OFF] = (fastrand() & 0xff); \ src_v[i + OFF] = (fastrand() & 0xff); \
} \ } \
memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \ memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
for (int i = 0; i < benchmark_iterations_; ++i) { \ FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \ src_v + OFF, kStrideUV, dst_argb_b + OFF, kStrideB, \
src_v + OFF, kStrideUV, dst_argb_b + OFF, \ kWidth, NEG kHeight); \
kStrideB, kWidth, NEG kHeight); \
} \
/* Convert to a 3rd format in 1 step and 2 steps and compare */ \ /* Convert to a 3rd format in 1 step and 2 steps and compare */ \
const int kStrideC = kWidth * BPP_C; \ const int kStrideC = kWidth * BPP_C; \
align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \ align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \ align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \ memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \ memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
FMT_PLANAR##To##FMT_C(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \ for (int i = 0; i < benchmark_iterations_; ++i) { \
src_v + OFF, kStrideUV, dst_argb_c + OFF, kStrideC, \ FMT_PLANAR##To##FMT_C(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
kWidth, NEG kHeight); \ src_v + OFF, kStrideUV, dst_argb_c + OFF, \
/* Convert B to C */ \ kStrideC, kWidth, NEG kHeight); \
FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \ /* Convert B to C */ \
kWidth, kHeight); \ FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, \
kStrideC, kWidth, kHeight); \
} \
for (int i = 0; i < kStrideC * kHeight; ++i) { \ for (int i = 0; i < kStrideC * kHeight; ++i) { \
EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]); \ EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]); \
} \ } \
@ -2877,26 +2878,28 @@ TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \ TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
benchmark_width_, _Opt, +, 0, FMT_C, BPP_C) benchmark_width_, _Opt, +, 0, FMT_C, BPP_C)
TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ABGR, 4)
TESTPLANARTOE(I420, 2, 2, ABGR, 1, 4, ARGB, 4) TESTPLANARTOE(I420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(J420, 2, 2, ARGB, 1, 4, ARGB, 4) TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ABGR, 4)
TESTPLANARTOE(J420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(U420, 2, 2, ARGB, 1, 4, ARGB, 4)
TESTPLANARTOE(U420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(I420, 2, 2, BGRA, 1, 4, ARGB, 4)
TESTPLANARTOE(I420, 2, 2, RGBA, 1, 4, ARGB, 4)
TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, ARGB, 4)
TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, RGB24, 3)
TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, RAW, 3)
TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RAW, 3) TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RAW, 3)
TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RGB24, 3)
TESTPLANARTOE(I420, 2, 2, BGRA, 1, 4, ARGB, 4)
TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, ARGB, 4) TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, RGB24, 1, 3, ARGB, 4) TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, RGB24, 3)
TESTPLANARTOE(H420, 2, 2, RAW, 1, 3, RGB24, 3) TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, RGB24, 1, 3, RAW, 3) TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, RAW, 3)
TESTPLANARTOE(I420, 2, 2, RGBA, 1, 4, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, ABGR, 4)
TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, RAW, 3) TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, RAW, 3)
TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, RGB24, 3)
TESTPLANARTOE(H420, 2, 2, RAW, 1, 3, ARGB, 4) TESTPLANARTOE(H420, 2, 2, RAW, 1, 3, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, RAW, 1, 3, RGB24, 3)
TESTPLANARTOE(H420, 2, 2, RGB24, 1, 3, ARGB, 4)
TESTPLANARTOE(H420, 2, 2, RGB24, 1, 3, RAW, 3)
TESTPLANARTOE(J420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(J420, 2, 2, ARGB, 1, 4, ARGB, 4)
TESTPLANARTOE(U420, 2, 2, ABGR, 1, 4, ARGB, 4)
TESTPLANARTOE(U420, 2, 2, ARGB, 1, 4, ARGB, 4)
#ifdef LITTLE_ENDIAN_ONLY_TEST #ifdef LITTLE_ENDIAN_ONLY_TEST
TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RGB565, 2) TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RGB565, 2)
TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ARGB1555, 2) TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ARGB1555, 2)
@ -2932,7 +2935,7 @@ TESTPLANARTOE(I422, 2, 1, UYVY, 2, 4, ARGB, 4)
#define TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \ #define TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
W1280, N, NEG, OFF, FMT_C, BPP_C, ATTEN) \ W1280, N, NEG, OFF, FMT_C, BPP_C, ATTEN) \
TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) { \ TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##To##FMT_C##N) { \
const int kWidth = W1280; \ const int kWidth = W1280; \
const int kHeight = benchmark_height_; \ const int kHeight = benchmark_height_; \
const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \ const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \
@ -2952,25 +2955,25 @@ TESTPLANARTOE(I422, 2, 1, UYVY, 2, 4, ARGB, 4)
src_v[i + OFF] = (fastrand() & 0xff); \ src_v[i + OFF] = (fastrand() & 0xff); \
} \ } \
memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \ memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
for (int i = 0; i < benchmark_iterations_; ++i) { \ FMT_PLANAR##To##FMT_B( \
FMT_PLANAR##To##FMT_B( \ src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \
src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \ src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), src_a + OFF, kWidth, \
src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), src_a + OFF, kWidth, \ dst_argb_b + OFF, kStrideB, kWidth, NEG kHeight, ATTEN); \
dst_argb_b + OFF, kStrideB, kWidth, NEG kHeight, ATTEN); \
} \
/* Convert to a 3rd format in 1 step and 2 steps and compare */ \ /* Convert to a 3rd format in 1 step and 2 steps and compare */ \
const int kStrideC = kWidth * BPP_C; \ const int kStrideC = kWidth * BPP_C; \
align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \ align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \ align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \ memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \ memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
FMT_PLANAR##To##FMT_C( \ for (int i = 0; i < benchmark_iterations_; ++i) { \
src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \ FMT_PLANAR##To##FMT_C( \
src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), src_a + OFF, kWidth, \ src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \
dst_argb_c + OFF, kStrideC, kWidth, NEG kHeight, ATTEN); \ src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), src_a + OFF, kWidth, \
/* Convert B to C */ \ dst_argb_c + OFF, kStrideC, kWidth, NEG kHeight, ATTEN); \
FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \ /* Convert B to C */ \
kWidth, kHeight); \ FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, \
kStrideC, kWidth, kHeight); \
} \
for (int i = 0; i < kStrideC * kHeight; ++i) { \ for (int i = 0; i < kStrideC * kHeight; ++i) { \
EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]); \ EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]); \
} \ } \
@ -3033,7 +3036,7 @@ TESTQPLANARTOE(V444Alpha, 1, 1, ABGR, 1, 4, ARGB, 4)
#define TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, W1280, N, NEG, \ #define TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, W1280, N, NEG, \
OFF, FMT_C, BPP_C) \ OFF, FMT_C, BPP_C) \
TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##_##FMT_C##N) { \ TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##To##FMT_C##N) { \
const int kWidth = W1280; \ const int kWidth = W1280; \
const int kHeight = benchmark_height_; \ const int kHeight = benchmark_height_; \
const int kStrideA = SUBSAMPLE(kWidth, SUB_A) * BPP_A; \ const int kStrideA = SUBSAMPLE(kWidth, SUB_A) * BPP_A; \
@ -3042,21 +3045,21 @@ TESTQPLANARTOE(V444Alpha, 1, 1, ABGR, 1, 4, ARGB, 4)
align_buffer_page_end(dst_argb_b, kStrideB* kHeight + OFF); \ align_buffer_page_end(dst_argb_b, kStrideB* kHeight + OFF); \
MemRandomize(src_argb_a + OFF, kStrideA * kHeight); \ MemRandomize(src_argb_a + OFF, kStrideA * kHeight); \
memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \ memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
for (int i = 0; i < benchmark_iterations_; ++i) { \ FMT_A##To##FMT_B(src_argb_a + OFF, kStrideA, dst_argb_b + OFF, kStrideB, \
FMT_A##To##FMT_B(src_argb_a + OFF, kStrideA, dst_argb_b + OFF, kStrideB, \ kWidth, NEG kHeight); \
kWidth, NEG kHeight); \
} \
/* Convert to a 3rd format in 1 step and 2 steps and compare */ \ /* Convert to a 3rd format in 1 step and 2 steps and compare */ \
const int kStrideC = kWidth * BPP_C; \ const int kStrideC = kWidth * BPP_C; \
align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \ align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \ align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \ memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \ memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
FMT_A##To##FMT_C(src_argb_a + OFF, kStrideA, dst_argb_c + OFF, kStrideC, \ for (int i = 0; i < benchmark_iterations_; ++i) { \
kWidth, NEG kHeight); \ FMT_A##To##FMT_C(src_argb_a + OFF, kStrideA, dst_argb_c + OFF, kStrideC, \
/* Convert B to C */ \ kWidth, NEG kHeight); \
FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \ /* Convert B to C */ \
kWidth, kHeight); \ FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, \
kStrideC, kWidth, kHeight); \
} \
for (int i = 0; i < kStrideC * kHeight; i += 4) { \ for (int i = 0; i < kStrideC * kHeight; i += 4) { \
EXPECT_EQ(dst_argb_c[i + OFF + 0], dst_argb_bc[i + OFF + 0]); \ EXPECT_EQ(dst_argb_c[i + OFF + 0], dst_argb_bc[i + OFF + 0]); \
EXPECT_EQ(dst_argb_c[i + OFF + 1], dst_argb_bc[i + OFF + 1]); \ EXPECT_EQ(dst_argb_c[i + OFF + 1], dst_argb_bc[i + OFF + 1]); \

View File

@ -72,26 +72,98 @@ TEST_F(LibYUVBaseTest, TestCpuHas) {
#endif #endif
} }
TEST_F(LibYUVBaseTest, TestCpuCompilerEnabled) { TEST_F(LibYUVBaseTest, TestCompilerMacros) {
#if defined(__aarch64__) // Tests all macros used in public headers.
printf("Arm64 build\n"); #ifdef __ATOMIC_RELAXED
printf("__ATOMIC_RELAXED %d\n", __ATOMIC_RELAXED);
#endif #endif
#if defined(__aarch64__) || defined(__ARM_NEON__) || defined(LIBYUV_NEON) #ifdef __cplusplus
printf("Neon build enabled\n"); printf("__cplusplus %ld\n", __cplusplus);
#endif #endif
#if defined(__x86_64__) || defined(_M_X64) #ifdef __clang_major__
printf("x64 build\n"); printf("__clang_major__ %d\n", __clang_major__);
#endif
#ifdef __clang_minor__
printf("__clang_minor__ %d\n", __clang_minor__);
#endif
#ifdef __GNUC__
printf("__GNUC__ %d\n", __GNUC__);
#endif
#ifdef __GNUC_MINOR__
printf("__GNUC_MINOR__ %d\n", __GNUC_MINOR__);
#endif
#ifdef __i386__
printf("__i386__ %d\n", __i386__);
#endif
#ifdef __mips
printf("__mips %d\n", __mips);
#endif
#ifdef __mips_isa_rev
printf("__mips_isa_rev %d\n", __mips_isa_rev);
#endif
#ifdef __x86_64__
printf("__x86_64__ %d\n", __x86_64__);
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
printf("_MSC_VER %d\n", _MSC_VER); printf("_MSC_VER %d\n", _MSC_VER);
#endif #endif
#if !defined(LIBYUV_DISABLE_X86) && \ #ifdef __aarch64__
(defined(GCC_HAS_AVX2) || defined(CLANG_HAS_AVX2) || \ printf("__aarch64__ %d\n", __aarch64__);
defined(VISUALC_HAS_AVX2)) #endif
printf("Has AVX2 1\n"); #ifdef __APPLE__
#else printf("__APPLE__ %d\n", __APPLE__);
printf("Has AVX2 0\n"); #endif
// If compiler does not support AVX2, the following function not expected: #ifdef __arm__
printf("__arm__ %d\n", __arm__);
#endif
#ifdef __clang__
printf("__clang__ %d\n", __clang__);
#endif
#ifdef __CLR_VER
printf("__CLR_VER %d\n", __CLR_VER);
#endif
#ifdef __CYGWIN__
printf("__CYGWIN__ %d\n", __CYGWIN__);
#endif
#ifdef __llvm__
printf("__llvm__ %d\n", __llvm__);
#endif
#ifdef __mips_msa
printf("__mips_msa %d\n", __mips_msa);
#endif
#ifdef __native_client__
printf("__native_client__ %d\n", __native_client__);
#endif
#ifdef __pic__
printf("__pic__ %d\n", __pic__);
#endif
#ifdef __pnacl__
printf("__pnacl__ %d\n", __pnacl__);
#endif
#ifdef _M_IX86
printf("_M_IX86 %d\n", _M_IX86);
#endif
#ifdef _M_X64
printf("_M_X64 %d\n", _M_X64);
#endif
#ifdef _MIPS_ARCH_LOONGSON3A
printf("_MIPS_ARCH_LOONGSON3A %d\n", _MIPS_ARCH_LOONGSON3A);
#endif
#ifdef _WIN32
printf("_WIN32 %d\n", _WIN32);
#endif
#ifdef GG_LONGLONG
printf("GG_LONGLONG %d\n", GG_LONGLONG);
#endif
#ifdef INT_TYPES_DEFINED
printf("INT_TYPES_DEFINED\n");
#endif
#ifdef __has_feature
printf("__has_feature\n");
#if __has_feature(memory_sanitizer)
printf("__has_feature(memory_sanitizer) %d\n",
__has_feature(memory_sanitizer));
#endif
#endif #endif
} }