Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2012 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #ifndef SkUtilsArm_DEFINED
     10 #define SkUtilsArm_DEFINED
     11 
     12 #include "SkUtils.h"
     13 
     14 // Define SK_ARM_NEON_MODE to one of the following values
     15 // corresponding respectively to:
     16 // - No ARM Neon support at all  (not targetting ARMv7-A, or don't have NEON)
     17 // - Full ARM Neon support (i.e. assume the CPU always supports it)
     18 // - Optional ARM Neon support (i.e. probe CPU at runtime)
     19 //
     20 #define SK_ARM_NEON_MODE_NONE     0
     21 #define SK_ARM_NEON_MODE_ALWAYS   1
     22 #define SK_ARM_NEON_MODE_DYNAMIC  2
     23 
     24 #if defined(SK_CPU_ARM32) && defined(__ARM_HAVE_OPTIONAL_NEON_SUPPORT)
     25 #  define SK_ARM_NEON_MODE  SK_ARM_NEON_MODE_DYNAMIC
     26 #elif defined(SK_CPU_ARM32) && defined(__ARM_HAVE_NEON) || defined(SK_CPU_ARM64)
     27 #  define SK_ARM_NEON_MODE  SK_ARM_NEON_MODE_ALWAYS
     28 #else
     29 #  define SK_ARM_NEON_MODE  SK_ARM_NEON_MODE_NONE
     30 #endif
     31 
     32 // Convenience test macros, always defined as 0 or 1
     33 #define SK_ARM_NEON_IS_NONE    (SK_ARM_NEON_MODE == SK_ARM_NEON_MODE_NONE)
     34 #define SK_ARM_NEON_IS_ALWAYS  (SK_ARM_NEON_MODE == SK_ARM_NEON_MODE_ALWAYS)
     35 #define SK_ARM_NEON_IS_DYNAMIC (SK_ARM_NEON_MODE == SK_ARM_NEON_MODE_DYNAMIC)
     36 
     37 // The sk_cpu_arm_has_neon() function returns true iff the target device
     38 // is ARMv7-A and supports Neon instructions. In DYNAMIC mode, this actually
     39 // probes the CPU at runtime (and caches the result).
     40 
     41 #if SK_ARM_NEON_IS_NONE
     42 static inline bool sk_cpu_arm_has_neon(void) {
     43     return false;
     44 }
     45 #elif SK_ARM_NEON_IS_ALWAYS
     46 static inline bool sk_cpu_arm_has_neon(void) {
     47     return true;
     48 }
     49 #else // SK_ARM_NEON_IS_DYNAMIC
     50 
     51 extern bool sk_cpu_arm_has_neon(void) SK_PURE_FUNC;
     52 #endif
     53 
     54 // Use SK_ARM_NEON_WRAP(symbol) to map 'symbol' to a NEON-specific symbol
     55 // when applicable. This will transform 'symbol' differently depending on
     56 // the current NEON configuration, i.e.:
     57 //
     58 //    NONE           -> 'symbol'
     59 //    ALWAYS         -> 'symbol_neon'
     60 //    DYNAMIC        -> 'symbol' or 'symbol_neon' depending on runtime check.
     61 //
     62 // The goal is to simplify user code, for example:
     63 //
     64 //      return SK_ARM_NEON_WRAP(do_something)(params);
     65 //
     66 // Replaces the equivalent:
     67 //
     68 //     #if SK_ARM_NEON_IS_NONE
     69 //       return do_something(params);
     70 //     #elif SK_ARM_NEON_IS_ALWAYS
     71 //       return do_something_neon(params);
     72 //     #elif SK_ARM_NEON_IS_DYNAMIC
     73 //       if (sk_cpu_arm_has_neon())
     74 //         return do_something_neon(params);
     75 //       else
     76 //         return do_something(params);
     77 //     #endif
     78 //
     79 #if SK_ARM_NEON_IS_NONE
     80 #  define SK_ARM_NEON_WRAP(x)   (x)
     81 #elif SK_ARM_NEON_IS_ALWAYS
     82 #  define SK_ARM_NEON_WRAP(x)   (x ## _neon)
     83 #elif SK_ARM_NEON_IS_DYNAMIC
     84 #  define SK_ARM_NEON_WRAP(x)   (sk_cpu_arm_has_neon() ? x ## _neon : x)
     85 #endif
     86 
     87 #endif // SkUtilsArm_DEFINED
     88