| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2012 The Android Open Source Project | 3 * Copyright 2012 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkUtilsArm.h" | 9 #include "SkUtilsArm.h" |
| 10 | 10 |
| 11 #if SK_ARM_NEON_IS_DYNAMIC | 11 #if SK_ARM_NEON_IS_DYNAMIC |
| 12 | 12 |
| 13 #include <unistd.h> | 13 #include <unistd.h> |
| 14 #include <fcntl.h> | 14 #include <fcntl.h> |
| 15 #include <errno.h> | 15 #include <errno.h> |
| 16 #include <string.h> | 16 #include <string.h> |
| 17 #include <pthread.h> | 17 #include <pthread.h> |
| 18 | 18 |
| 19 // Set USE_ANDROID_NDK_CPU_FEATURES to use the Android NDK's | 19 #if SK_BUILD_FOR_ANDROID |
| 20 // cpu-features helper library to detect NEON at runtime. See | |
| 21 // http://crbug.com/164154 to see why this is needed in Chromium | |
| 22 // for Android. | |
| 23 #if !defined(USE_ANDROID_NDK_CPU_FEATURES) | |
| 24 # if defined(SK_BUILD_FOR_ANDROID) | |
| 25 # define USE_ANDROID_NDK_CPU_FEATURES 1 | |
| 26 # else | |
| 27 # define USE_ANDROID_NDK_CPU_FEATURES 0 | |
| 28 # endif | |
| 29 #endif | |
| 30 | |
| 31 #if USE_ANDROID_NDK_CPU_FEATURES | |
| 32 # include <cpu-features.h> | 20 # include <cpu-features.h> |
| 33 #endif | 21 #endif |
| 34 | 22 |
| 35 // Set NEON_DEBUG to 1 to allow debugging of the CPU features probing. | |
| 36 // For now, we always set it for SK_DEBUG builds. | |
| 37 #ifdef SK_DEBUG | |
| 38 # define NEON_DEBUG 1 | |
| 39 #else | |
| 40 # define NEON_DEBUG 0 | |
| 41 #endif | |
| 42 | |
| 43 #if NEON_DEBUG | |
| 44 # ifdef SK_BUILD_FOR_ANDROID | |
| 45 // used to declare PROP_VALUE_MAX and __system_property_get() | |
| 46 # include <sys/system_properties.h> | |
| 47 # endif | |
| 48 #endif | |
| 49 | |
| 50 // A function used to determine at runtime if the target CPU supports | 23 // A function used to determine at runtime if the target CPU supports |
| 51 // the ARM NEON instruction set. This implementation is Linux-specific. | 24 // the ARM NEON instruction set. This implementation is Linux-specific. |
| 52 static bool sk_cpu_arm_check_neon(void) { | 25 static bool sk_cpu_arm_check_neon(void) { |
| 26 // If we fail any of the following, assume we don't have NEON instructions |
| 27 // This allows us to return immediately in case of error. |
| 53 bool result = false; | 28 bool result = false; |
| 54 | 29 |
| 55 #if NEON_DEBUG | 30 // Use the Android NDK's cpu-features helper library to detect NEON at runtime. |
| 56 // Allow forcing the mode through the environment during debugging. | 31 // See http://crbug.com/164154 to see why this is needed in Chromium for Android
. |
| 57 # ifdef SK_BUILD_FOR_ANDROID | 32 #ifdef SK_BUILD_FOR_ANDROID |
| 58 // On Android, we use a system property | |
| 59 # define PROP_NAME "debug.skia.arm_neon_mode" | |
| 60 char prop[PROP_VALUE_MAX]; | |
| 61 if (__system_property_get(PROP_NAME, prop) > 0) { | |
| 62 # else | |
| 63 # define PROP_NAME "SKIA_ARM_NEON_MODE" | |
| 64 // On ARM Linux, we use an environment variable | |
| 65 const char* prop = getenv(PROP_NAME); | |
| 66 if (prop != NULL) { | |
| 67 # endif | |
| 68 SkDebugf("%s: %s", PROP_NAME, prop); | |
| 69 if (!strcmp(prop, "1")) { | |
| 70 SkDebugf("Forcing ARM Neon mode to full!\n"); | |
| 71 return true; | |
| 72 } | |
| 73 if (!strcmp(prop, "0")) { | |
| 74 SkDebugf("Disabling ARM NEON mode\n"); | |
| 75 return false; | |
| 76 } | |
| 77 } | |
| 78 SkDebugf("Running dynamic CPU feature detection\n"); | |
| 79 #endif | |
| 80 | |
| 81 #if USE_ANDROID_NDK_CPU_FEATURES | |
| 82 | 33 |
| 83 result = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; | 34 result = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; |
| 84 | 35 |
| 85 #else // USE_ANDROID_NDK_CPU_FEATURES | 36 #else // SK_BUILD_FOR_ANDROID |
| 86 | 37 |
| 87 // There is no user-accessible CPUID instruction on ARM that we can use. | 38 // There is no user-accessible CPUID instruction on ARM that we can use. |
| 88 // Instead, we must parse /proc/cpuinfo and look for the 'neon' feature. | 39 // Instead, we must parse /proc/cpuinfo and look for the 'neon' feature. |
| 89 // For example, here's a typical output (Nexus S running ICS 4.0.3): | 40 // For example, here's a typical output (Nexus S running ICS 4.0.3): |
| 90 /* | 41 /* |
| 91 Processor : ARMv7 Processor rev 2 (v7l) | 42 Processor : ARMv7 Processor rev 2 (v7l) |
| 92 BogoMIPS : 994.65 | 43 BogoMIPS : 994.65 |
| 93 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 | 44 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 |
| 94 CPU implementer : 0x41 | 45 CPU implementer : 0x41 |
| 95 CPU architecture: 7 | 46 CPU architecture: 7 |
| 96 CPU variant : 0x2 | 47 CPU variant : 0x2 |
| 97 CPU part : 0xc08 | 48 CPU part : 0xc08 |
| 98 CPU revision : 2 | 49 CPU revision : 2 |
| 99 | 50 |
| 100 Hardware : herring | 51 Hardware : herring |
| 101 Revision : 000b | 52 Revision : 000b |
| 102 Serial : 3833c77d6dc000ec | 53 Serial : 3833c77d6dc000ec |
| 103 */ | 54 */ |
| 104 char buffer[4096]; | 55 char buffer[4096]; |
| 105 | 56 |
| 106 // If we fail any of the following, assume we don't have NEON instructions | |
| 107 // This allows us to return immediately in case of error. | |
| 108 result = false; | |
| 109 | |
| 110 do { | 57 do { |
| 111 // open /proc/cpuinfo | 58 // open /proc/cpuinfo |
| 112 int fd = TEMP_FAILURE_RETRY(open("/proc/cpuinfo", O_RDONLY)); | 59 int fd = TEMP_FAILURE_RETRY(open("/proc/cpuinfo", O_RDONLY)); |
| 113 if (fd < 0) { | 60 if (fd < 0) { |
| 114 SkDebugf("Could not open /proc/cpuinfo: %s\n", strerror(errno)); | 61 SkDebugf("Could not open /proc/cpuinfo: %s\n", strerror(errno)); |
| 115 break; | 62 break; |
| 116 } | 63 } |
| 117 | 64 |
| 118 // Read the file. To simplify our search, we're going to place two | 65 // Read the file. To simplify our search, we're going to place two |
| 119 // sentinel '\n' characters: one at the start of the buffer, and one at | 66 // sentinel '\n' characters: one at the start of the buffer, and one at |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 113 |
| 167 // Ensure it is followed by a space or a newline. | 114 // Ensure it is followed by a space or a newline. |
| 168 if (flag[neon_len] != ' ' && flag[neon_len] != '\n') | 115 if (flag[neon_len] != ' ' && flag[neon_len] != '\n') |
| 169 break; | 116 break; |
| 170 | 117 |
| 171 // Fine, we support Arm NEON ! | 118 // Fine, we support Arm NEON ! |
| 172 result = true; | 119 result = true; |
| 173 | 120 |
| 174 } while (0); | 121 } while (0); |
| 175 | 122 |
| 176 #endif // USE_ANDROID_NDK_CPU_FEATURES | 123 #endif // SK_BUILD_FOR_ANDROID |
| 177 | 124 |
| 178 if (result) { | 125 if (result) { |
| 179 SkDebugf("Device supports ARM NEON instructions!\n"); | 126 SkDEBUGF(("Device supports ARM NEON instructions!\n")); |
| 180 } else { | 127 } else { |
| 181 SkDebugf("Device does NOT support ARM NEON instructions!\n"); | 128 SkDEBUGF(("Device does NOT support ARM NEON instructions!\n")); |
| 182 } | 129 } |
| 183 return result; | 130 return result; |
| 184 } | 131 } |
| 185 | 132 |
| 186 static pthread_once_t sOnce; | 133 static pthread_once_t sOnce; |
| 187 static bool sHasArmNeon; | 134 static bool sHasArmNeon; |
| 188 | 135 |
| 189 // called through pthread_once() | 136 // called through pthread_once() |
| 190 void sk_cpu_arm_probe_features(void) { | 137 void sk_cpu_arm_probe_features(void) { |
| 191 sHasArmNeon = sk_cpu_arm_check_neon(); | 138 sHasArmNeon = sk_cpu_arm_check_neon(); |
| 192 } | 139 } |
| 193 | 140 |
| 194 bool sk_cpu_arm_has_neon(void) { | 141 bool sk_cpu_arm_has_neon(void) { |
| 195 pthread_once(&sOnce, sk_cpu_arm_probe_features); | 142 pthread_once(&sOnce, sk_cpu_arm_probe_features); |
| 196 return sHasArmNeon; | 143 return sHasArmNeon; |
| 197 } | 144 } |
| 198 | 145 |
| 199 #endif // SK_ARM_NEON_IS_DYNAMIC | 146 #endif // SK_ARM_NEON_IS_DYNAMIC |
| OLD | NEW |