diff --git a/configure.ac b/configure.ac index 258d418b..d5658228 100644 --- a/configure.ac +++ b/configure.ac @@ -178,6 +178,60 @@ AS_IF([test "x$enable_sse2" != "xno"], [ CFLAGS=$SAVED_CFLAGS]) AC_SUBST([SSE2_FLAGS])]) +AC_ARG_ENABLE([neon], + AS_HELP_STRING([--disable-neon], + [Disable detection of NEON support + @<:@default=auto@:>@])) + +AC_ARG_ENABLE([neon_rtcd], + AS_HELP_STRING([--disable-neon-rtcd], + [Disable runtime detection of NEON support via + /proc/cpuinfo on Linux hosts + @<:@default=auto@:>@])) +# For ARM(7) hosts: +# Both NEON flags unset and NEON support detected = build all modules with NEON +# NEON detected with the use of -mfpu=neon = build only NEON modules with NEON +AS_IF([test "x$enable_neon" != "xno"], [ + case "$host_cpu" in + arm|armv7*) + dnl Test for NEON support with no flags. + AC_CHECK_HEADER([arm_neon.h], + [AC_DEFINE(WEBP_HAVE_NEON, [1], + [Set to 1 if NEON is supported])], + dnl Test for NEON support using -mfpu=neon + [unset ac_cv_header_arm_neon_h + NEON_FLAGS="$INTRINSICS_CFLAGS $NEON_FLAGS" + TEST_AND_ADD_CFLAGS([NEON_FLAGS], [-mfpu=neon]) + AS_IF([test -n "$NEON_FLAGS"], [ + SAVED_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $NEON_FLAGS" + AC_CHECK_HEADER([arm_neon.h], + [AS_IF([test "${host_os%%-*}" = "linux" -o \ + "x$enable_neon_rtcd" = "xno"], [ + AC_DEFINE(WEBP_HAVE_NEON, [1], + [Set to 1 if NEON is supported])], + [AC_MSG_WARN(m4_normalize([NEON runtime + cpu-detection is unavailble for + ${host_os%%-*}. Force with + CFLAGS=-mfpu=neon or + --disable-neon-rtcd.])) + enable_neon_rtcd=no + NEON_FLAGS=""])], + [NEON_FLAGS=""]) + CFLAGS=$SAVED_CFLAGS + AS_IF([test -n "$NEON_FLAGS"], [ + dnl If NEON is available and rtcd is disabled apply + dnl NEON_FLAGS globally. + AS_IF([test "x$enable_neon_rtcd" = "xno"], [ + AM_CFLAGS="$AM_CFLAGS $NEON_FLAGS" + NEON_FLAGS=""], + [AC_DEFINE(WEBP_HAVE_NEON_RTCD, [1], + [Set to 1 if runtime detection of NEON + is enabled])])])])]) + ;; + esac + AC_SUBST([NEON_FLAGS])]) + dnl === CLEAR_LIBVARS([var_pfx]) dnl === Clears _{INCLUDES,LIBS}. AC_DEFUN([CLEAR_LIBVARS], [$1_INCLUDES=""; $1_LIBS=""]) diff --git a/src/dsp/Makefile.am b/src/dsp/Makefile.am index e45c5907..c1a9d827 100644 --- a/src/dsp/Makefile.am +++ b/src/dsp/Makefile.am @@ -1,6 +1,7 @@ noinst_LTLIBRARIES = libwebpdsp.la libwebpdsp_avx2.la noinst_LTLIBRARIES += libwebpdsp_sse2.la libwebpdspdecode_sse2.la noinst_LTLIBRARIES += libwebpdsp_sse41.la libwebpdspdecode_sse41.la +noinst_LTLIBRARIES += libwebpdsp_neon.la libwebpdspdecode_neon.la if BUILD_LIBWEBPDECODER noinst_LTLIBRARIES += libwebpdspdecode.la @@ -18,23 +19,18 @@ COMMON_SOURCES += dec.c COMMON_SOURCES += dec_clip_tables.c COMMON_SOURCES += dec_mips32.c COMMON_SOURCES += dec_mips_dsp_r2.c -COMMON_SOURCES += dec_neon.c COMMON_SOURCES += dsp.h COMMON_SOURCES += filters.c COMMON_SOURCES += filters_mips_dsp_r2.c COMMON_SOURCES += lossless.c COMMON_SOURCES += lossless.h COMMON_SOURCES += lossless_mips_dsp_r2.c -COMMON_SOURCES += lossless_neon.c COMMON_SOURCES += mips_macro.h -COMMON_SOURCES += neon.h COMMON_SOURCES += rescaler.c COMMON_SOURCES += rescaler_mips32.c COMMON_SOURCES += rescaler_mips_dsp_r2.c -COMMON_SOURCES += rescaler_neon.c COMMON_SOURCES += upsampling.c COMMON_SOURCES += upsampling_mips_dsp_r2.c -COMMON_SOURCES += upsampling_neon.c COMMON_SOURCES += yuv.c COMMON_SOURCES += yuv.h COMMON_SOURCES += yuv_mips32.c @@ -49,11 +45,9 @@ ENC_SOURCES += cost_mips_dsp_r2.c ENC_SOURCES += enc.c ENC_SOURCES += enc_mips32.c ENC_SOURCES += enc_mips_dsp_r2.c -ENC_SOURCES += enc_neon.c ENC_SOURCES += lossless_enc.c ENC_SOURCES += lossless_enc_mips32.c ENC_SOURCES += lossless_enc_mips_dsp_r2.c -ENC_SOURCES += lossless_enc_neon.c libwebpdsp_avx2_la_SOURCES = libwebpdsp_avx2_la_SOURCES += enc_avx2.c @@ -77,6 +71,15 @@ libwebpdspdecode_sse2_la_SOURCES += yuv_sse2.c libwebpdspdecode_sse2_la_CPPFLAGS = $(libwebpdsp_sse2_la_CPPFLAGS) libwebpdspdecode_sse2_la_CFLAGS = $(libwebpdsp_sse2_la_CFLAGS) +libwebpdspdecode_neon_la_SOURCES = +libwebpdspdecode_neon_la_SOURCES += dec_neon.c +libwebpdspdecode_neon_la_SOURCES += lossless_neon.c +libwebpdspdecode_neon_la_SOURCES += neon.h +libwebpdspdecode_neon_la_SOURCES += rescaler_neon.c +libwebpdspdecode_neon_la_SOURCES += upsampling_neon.c +libwebpdspdecode_neon_la_CPPFLAGS = $(libwebpdsp_neon_la_CPPFLAGS) +libwebpdspdecode_neon_la_CFLAGS = $(libwebpdsp_neon_la_CFLAGS) + libwebpdsp_sse2_la_SOURCES = libwebpdsp_sse2_la_SOURCES += argb_sse2.c libwebpdsp_sse2_la_SOURCES += cost_sse2.c @@ -93,6 +96,13 @@ libwebpdsp_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) libwebpdsp_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS) libwebpdsp_sse41_la_LIBADD = libwebpdspdecode_sse41.la +libwebpdsp_neon_la_SOURCES = +libwebpdsp_neon_la_SOURCES += enc_neon.c +libwebpdsp_neon_la_SOURCES += lossless_enc_neon.c +libwebpdsp_neon_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS) +libwebpdsp_neon_la_LIBADD = libwebpdspdecode_neon.la + libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES) noinst_HEADERS = @@ -106,6 +116,7 @@ libwebpdsp_la_LDFLAGS = -lm libwebpdsp_la_LIBADD = libwebpdsp_la_LIBADD += libwebpdsp_avx2.la libwebpdsp_sse2.la libwebpdsp_la_LIBADD += libwebpdsp_sse41.la +libwebpdsp_la_LIBADD += libwebpdsp_neon.la if BUILD_LIBWEBPDECODER libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES) @@ -115,4 +126,5 @@ if BUILD_LIBWEBPDECODER libwebpdspdecode_la_LIBADD = libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse2.la libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse41.la + libwebpdspdecode_la_LIBADD += libwebpdspdecode_neon.la endif diff --git a/src/dsp/cpu.c b/src/dsp/cpu.c index 8844cb40..4aa4abbc 100644 --- a/src/dsp/cpu.c +++ b/src/dsp/cpu.c @@ -13,6 +13,11 @@ #include "./dsp.h" +#if defined(WEBP_HAVE_NEON_RTCD) +#include +#include +#endif + #if defined(WEBP_ANDROID_NEON) #include #endif @@ -142,8 +147,27 @@ VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; // define a dummy function to enable turning off NEON at runtime by setting // VP8DecGetCPUInfo = NULL static int armCPUInfo(CPUFeature feature) { - (void)feature; + if (feature != kNEON) return 0; +#if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD) + { + int has_neon = 0; + char line[200]; + FILE* const cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo == NULL) return 0; + while (fgets(line, sizeof(line), cpuinfo)) { + if (!strncmp(line, "Features", 8)) { + if (strstr(line, " neon ") != NULL) { + has_neon = 1; + break; + } + } + } + fclose(cpuinfo); + return has_neon; + } +#else return 1; +#endif } VP8CPUInfo VP8GetCPUInfo = armCPUInfo; #elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index 10c16ee4..f27e83d6 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -72,7 +72,8 @@ extern "C" { // The intrinsics currently cause compiler errors with arm-nacl-gcc and the // inline assembly would need to be modified for use with Native Client. #if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \ - defined(__aarch64__)) && !defined(__native_client__) + defined(__aarch64__) || defined(WEBP_HAVE_NEON)) && \ + !defined(__native_client__) #define WEBP_USE_NEON #endif