gfx/cairo/libpixman/src/pixman-arm.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /*
michael@0 2 * Copyright © 2000 SuSE, Inc.
michael@0 3 * Copyright © 2007 Red Hat, Inc.
michael@0 4 *
michael@0 5 * Permission to use, copy, modify, distribute, and sell this software and its
michael@0 6 * documentation for any purpose is hereby granted without fee, provided that
michael@0 7 * the above copyright notice appear in all copies and that both that
michael@0 8 * copyright notice and this permission notice appear in supporting
michael@0 9 * documentation, and that the name of SuSE not be used in advertising or
michael@0 10 * publicity pertaining to distribution of the software without specific,
michael@0 11 * written prior permission. SuSE makes no representations about the
michael@0 12 * suitability of this software for any purpose. It is provided "as is"
michael@0 13 * without express or implied warranty.
michael@0 14 *
michael@0 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
michael@0 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
michael@0 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
michael@0 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
michael@0 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
michael@0 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
michael@0 21 */
michael@0 22 #ifdef HAVE_CONFIG_H
michael@0 23 #include <config.h>
michael@0 24 #endif
michael@0 25
michael@0 26 #include "pixman-private.h"
michael@0 27
michael@0 28 typedef enum
michael@0 29 {
michael@0 30 ARM_V7 = (1 << 0),
michael@0 31 ARM_V6 = (1 << 1),
michael@0 32 ARM_VFP = (1 << 2),
michael@0 33 ARM_NEON = (1 << 3),
michael@0 34 ARM_IWMMXT = (1 << 4)
michael@0 35 } arm_cpu_features_t;
michael@0 36
michael@0 37 #if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
michael@0 38
michael@0 39 #if defined(_MSC_VER)
michael@0 40
michael@0 41 /* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
michael@0 42 #include <windows.h>
michael@0 43
michael@0 44 extern int pixman_msvc_try_arm_neon_op ();
michael@0 45 extern int pixman_msvc_try_arm_simd_op ();
michael@0 46
michael@0 47 static arm_cpu_features_t
michael@0 48 detect_cpu_features (void)
michael@0 49 {
michael@0 50 arm_cpu_features_t features = 0;
michael@0 51
michael@0 52 __try
michael@0 53 {
michael@0 54 pixman_msvc_try_arm_simd_op ();
michael@0 55 features |= ARM_V6;
michael@0 56 }
michael@0 57 __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
michael@0 58 {
michael@0 59 }
michael@0 60
michael@0 61 __try
michael@0 62 {
michael@0 63 pixman_msvc_try_arm_neon_op ();
michael@0 64 features |= ARM_NEON;
michael@0 65 }
michael@0 66 __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
michael@0 67 {
michael@0 68 }
michael@0 69
michael@0 70 return features;
michael@0 71 }
michael@0 72
michael@0 73 #elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */
michael@0 74
michael@0 75 #include "TargetConditionals.h"
michael@0 76
michael@0 77 static arm_cpu_features_t
michael@0 78 detect_cpu_features (void)
michael@0 79 {
michael@0 80 arm_cpu_features_t features = 0;
michael@0 81
michael@0 82 features |= ARM_V6;
michael@0 83
michael@0 84 /* Detection of ARM NEON on iOS is fairly simple because iOS binaries
michael@0 85 * contain separate executable images for each processor architecture.
michael@0 86 * So all we have to do is detect the armv7 architecture build. The
michael@0 87 * operating system automatically runs the armv7 binary for armv7 devices
michael@0 88 * and the armv6 binary for armv6 devices.
michael@0 89 */
michael@0 90 #if defined(__ARM_NEON__)
michael@0 91 features |= ARM_NEON;
michael@0 92 #endif
michael@0 93
michael@0 94 return features;
michael@0 95 }
michael@0 96
michael@0 97 #elif defined(__ANDROID__) || defined(ANDROID) /* Android */
michael@0 98
michael@0 99 static arm_cpu_features_t
michael@0 100 detect_cpu_features (void)
michael@0 101 {
michael@0 102 arm_cpu_features_t features = 0;
michael@0 103 char buf[1024];
michael@0 104 char* pos;
michael@0 105 const char* ver_token = "CPU architecture: ";
michael@0 106 FILE* f = fopen("/proc/cpuinfo", "r");
michael@0 107 if (!f) {
michael@0 108 return features;
michael@0 109 }
michael@0 110
michael@0 111 fread(buf, sizeof(char), sizeof(buf), f);
michael@0 112 fclose(f);
michael@0 113 pos = strstr(buf, ver_token);
michael@0 114 if (pos) {
michael@0 115 char vchar = *(pos + strlen(ver_token));
michael@0 116 if (vchar >= '0' && vchar <= '9') {
michael@0 117 int ver = vchar - '0';
michael@0 118 if (ver >= 7)
michael@0 119 features |= ARM_V7;
michael@0 120 }
michael@0 121 }
michael@0 122 if (strstr(buf, "neon") != NULL)
michael@0 123 features |= ARM_NEON;
michael@0 124 if (strstr(buf, "vfp") != NULL)
michael@0 125 features |= ARM_VFP;
michael@0 126
michael@0 127 return features;
michael@0 128 }
michael@0 129
michael@0 130 #elif defined (__linux__) /* linux ELF */
michael@0 131
michael@0 132 #include <unistd.h>
michael@0 133 #include <sys/types.h>
michael@0 134 #include <sys/stat.h>
michael@0 135 #include <sys/mman.h>
michael@0 136 #include <fcntl.h>
michael@0 137 #include <string.h>
michael@0 138 #include <elf.h>
michael@0 139
michael@0 140 static arm_cpu_features_t
michael@0 141 detect_cpu_features (void)
michael@0 142 {
michael@0 143 arm_cpu_features_t features = 0;
michael@0 144 Elf32_auxv_t aux;
michael@0 145 int fd;
michael@0 146
michael@0 147 fd = open ("/proc/self/auxv", O_RDONLY);
michael@0 148 if (fd >= 0)
michael@0 149 {
michael@0 150 while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
michael@0 151 {
michael@0 152 if (aux.a_type == AT_HWCAP)
michael@0 153 {
michael@0 154 uint32_t hwcap = aux.a_un.a_val;
michael@0 155
michael@0 156 /* hardcode these values to avoid depending on specific
michael@0 157 * versions of the hwcap header, e.g. HWCAP_NEON
michael@0 158 */
michael@0 159 if ((hwcap & 64) != 0)
michael@0 160 features |= ARM_VFP;
michael@0 161 if ((hwcap & 512) != 0)
michael@0 162 features |= ARM_IWMMXT;
michael@0 163 /* this flag is only present on kernel 2.6.29 */
michael@0 164 if ((hwcap & 4096) != 0)
michael@0 165 features |= ARM_NEON;
michael@0 166 }
michael@0 167 else if (aux.a_type == AT_PLATFORM)
michael@0 168 {
michael@0 169 const char *plat = (const char*) aux.a_un.a_val;
michael@0 170
michael@0 171 if (strncmp (plat, "v7l", 3) == 0)
michael@0 172 features |= (ARM_V7 | ARM_V6);
michael@0 173 else if (strncmp (plat, "v6l", 3) == 0)
michael@0 174 features |= ARM_V6;
michael@0 175 }
michael@0 176 }
michael@0 177 close (fd);
michael@0 178 }
michael@0 179
michael@0 180 return features;
michael@0 181 }
michael@0 182
michael@0 183 #else /* Unknown */
michael@0 184
michael@0 185 static arm_cpu_features_t
michael@0 186 detect_cpu_features (void)
michael@0 187 {
michael@0 188 return 0;
michael@0 189 }
michael@0 190
michael@0 191 #endif /* Linux elf */
michael@0 192
michael@0 193 static pixman_bool_t
michael@0 194 have_feature (arm_cpu_features_t feature)
michael@0 195 {
michael@0 196 static pixman_bool_t initialized;
michael@0 197 static arm_cpu_features_t features;
michael@0 198
michael@0 199 if (!initialized)
michael@0 200 {
michael@0 201 features = detect_cpu_features();
michael@0 202 initialized = TRUE;
michael@0 203 }
michael@0 204
michael@0 205 return (features & feature) == feature;
michael@0 206 }
michael@0 207
michael@0 208 #endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
michael@0 209
michael@0 210 pixman_implementation_t *
michael@0 211 _pixman_arm_get_implementations (pixman_implementation_t *imp)
michael@0 212 {
michael@0 213 #ifdef USE_ARM_SIMD
michael@0 214 if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6))
michael@0 215 imp = _pixman_implementation_create_arm_simd (imp);
michael@0 216 #endif
michael@0 217
michael@0 218 #ifdef USE_ARM_IWMMXT
michael@0 219 if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT))
michael@0 220 imp = _pixman_implementation_create_mmx (imp);
michael@0 221 #endif
michael@0 222
michael@0 223 #ifdef USE_ARM_NEON
michael@0 224 if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON))
michael@0 225 imp = _pixman_implementation_create_arm_neon (imp);
michael@0 226 #endif
michael@0 227
michael@0 228 return imp;
michael@0 229 }

mercurial