|
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_ARM) && defined(__ARM_HAVE_OPTIONAL_NEON_SUPPORT) |
|
25 # define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_DYNAMIC |
|
26 #elif defined(SK_CPU_ARM) && defined(__ARM_HAVE_NEON) |
|
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 |