cpuinfo: more work on SDL_HasNEON().
authorRyan C. Gordon <icculus@icculus.org>
Thu, 17 Nov 2016 15:57:58 -0500
changeset 10624294ee69a9f11
parent 10623 3b93b7acc1b4
child 10625 d40f7ebf34eb
cpuinfo: more work on SDL_HasNEON().
src/cpuinfo/SDL_cpuinfo.c
     1.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Thu Nov 17 01:41:56 2016 -0500
     1.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Thu Nov 17 15:57:58 2016 -0500
     1.3 @@ -50,13 +50,7 @@
     1.4  #include <setjmp.h>
     1.5  #endif
     1.6  
     1.7 -#if 0  /* !!! FIXME */
     1.8 -#if defined(__ANDROID__) && defined(__ARM_ARCH)
     1.9 -#include <cpu-features.h>
    1.10 -#endif
    1.11 -#endif
    1.12 -
    1.13 -#if defined(__LINUX__) && defined(__ARM_ARCH) && HAVE_GETAUXVAL
    1.14 +#if defined(__LINUX__) && defined(__ARM_ARCH)
    1.15  #include <sys/auxv.h>
    1.16  #include <asm/hwcap.h>
    1.17  #endif
    1.18 @@ -300,38 +294,61 @@
    1.19      return altivec;
    1.20  }
    1.21  
    1.22 +#if (defined(__LINUX__) || defined(__ANDROID__)) && !HAVE_GETAUXVAL
    1.23 +static int
    1.24 +readProcAuxvForNeon(void)
    1.25 +{
    1.26 +    int neon = 0;
    1.27 +    int kv[2];
    1.28 +    const int fd = open("/proc/self/auxv", O_RDONLY);
    1.29 +
    1.30 +    if (fd == -1) {
    1.31 +        return 0;
    1.32 +    }
    1.33 +
    1.34 +    while (read(fd, kv, sizeof (kv)) == sizeof (kv)) {
    1.35 +        if (kv[0] == AT_HWCAP) {
    1.36 +            neon = ((kv[1] & HWCAP_NEON) == HWCAP_NEON);
    1.37 +            break;
    1.38 +        }
    1.39 +    }
    1.40 +
    1.41 +    close(fd);
    1.42 +
    1.43 +    return neon;
    1.44 +}
    1.45 +#endif
    1.46 +
    1.47 +
    1.48  static int
    1.49  CPU_haveNEON(void)
    1.50  {
    1.51 -    int neon = 0;
    1.52 -
    1.53  /* The way you detect NEON is a privileged instruction on ARM, so you have
    1.54     query the OS kernel in a platform-specific way. :/ */
    1.55 -#ifndef SDL_CPUINFO_DISABLED
    1.56 -#if defined(__APPLE__) && defined(__ARM_ARCH)
    1.57 +#if defined(SDL_CPUINFO_DISABLED) || !defined(__ARM_ARCH)
    1.58 +    return 0;
    1.59 +#elif __ARM_ARCH >= 8
    1.60 +    return 1;  // ARMv8 always has non-optional NEON support.
    1.61 +#elif defined(__APPLE__)
    1.62      /* all hardware that runs iOS 5 and later support NEON, but check anyhow */
    1.63 +    int neon = 0;
    1.64      size_t length = sizeof (neon);
    1.65      const int error = sysctlbyname("hw.optional.neon", &neon, &length, NULL, 0);
    1.66 -    if (!error)
    1.67 -        neon = (neon != 0);
    1.68 -#elif 0 && defined(__ANDROID__) && defined(__ARM_ARCH)  /* !!! FIXME */
    1.69 -    if ( (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM) &&
    1.70 -         ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0) ) {
    1.71 -        neon = 1;
    1.72 -    }
    1.73 -#elif defined(__LINUX__) && defined(__ARM_ARCH) && HAVE_GETAUXVAL
    1.74 -    if (getauxval(AT_HWCAP) & HWCAP_NEON) {
    1.75 -        neon = 1;
    1.76 -    }
    1.77 +    return (!error) && (neon != 0);
    1.78 +/* Android offers a static library for this but all it does is parse /proc/cpuinfo */
    1.79 +#elif (defined(__LINUX__) || defined(__ANDROID__)) && HAVE_GETAUXVAL
    1.80 +    return ((getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON)
    1.81 +#elif (defined(__LINUX__) || defined(__ANDROID__))
    1.82 +    return readProcAuxvForNeon();
    1.83  #elif (defined(__WINDOWS__) || defined(__WINRT__)) && defined(_M_ARM)
    1.84      /* All WinRT ARM devices are required to support NEON, but just in case. */
    1.85      if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)) {
    1.86          neon = 1;
    1.87      }
    1.88 +#else
    1.89 +#warning SDL_HasNEON is not implemented for this ARM platform. Write me.
    1.90  #endif
    1.91  #endif
    1.92 -
    1.93 -    return neon;
    1.94  }
    1.95  
    1.96  static int