1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-cpu.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,799 @@ 1.4 +/* 1.5 + * Copyright © 2000 SuSE, Inc. 1.6 + * Copyright © 2007 Red Hat, Inc. 1.7 + * 1.8 + * Permission to use, copy, modify, distribute, and sell this software and its 1.9 + * documentation for any purpose is hereby granted without fee, provided that 1.10 + * the above copyright notice appear in all copies and that both that 1.11 + * copyright notice and this permission notice appear in supporting 1.12 + * documentation, and that the name of SuSE not be used in advertising or 1.13 + * publicity pertaining to distribution of the software without specific, 1.14 + * written prior permission. SuSE makes no representations about the 1.15 + * suitability of this software for any purpose. It is provided "as is" 1.16 + * without express or implied warranty. 1.17 + * 1.18 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 1.20 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.21 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1.22 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1.23 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.24 + */ 1.25 +#ifdef HAVE_CONFIG_H 1.26 +#include <config.h> 1.27 +#endif 1.28 + 1.29 +#include <string.h> 1.30 +#include <stdlib.h> 1.31 + 1.32 +#if defined(USE_ARM_SIMD) && defined(_MSC_VER) 1.33 +/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ 1.34 +#include <windows.h> 1.35 +#endif 1.36 + 1.37 +#if defined(__APPLE__) 1.38 +#include "TargetConditionals.h" 1.39 +#endif 1.40 + 1.41 +#include "pixman-private.h" 1.42 + 1.43 +#ifdef USE_VMX 1.44 + 1.45 +/* The CPU detection code needs to be in a file not compiled with 1.46 + * "-maltivec -mabi=altivec", as gcc would try to save vector register 1.47 + * across function calls causing SIGILL on cpus without Altivec/vmx. 1.48 + */ 1.49 +static pixman_bool_t initialized = FALSE; 1.50 +static volatile pixman_bool_t have_vmx = TRUE; 1.51 + 1.52 +#ifdef __APPLE__ 1.53 +#include <sys/sysctl.h> 1.54 + 1.55 +static pixman_bool_t 1.56 +pixman_have_vmx (void) 1.57 +{ 1.58 + if (!initialized) 1.59 + { 1.60 + size_t length = sizeof(have_vmx); 1.61 + int error = 1.62 + sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0); 1.63 + 1.64 + if (error) 1.65 + have_vmx = FALSE; 1.66 + 1.67 + initialized = TRUE; 1.68 + } 1.69 + return have_vmx; 1.70 +} 1.71 + 1.72 +#elif defined (__OpenBSD__) 1.73 +#include <sys/param.h> 1.74 +#include <sys/sysctl.h> 1.75 +#include <machine/cpu.h> 1.76 + 1.77 +static pixman_bool_t 1.78 +pixman_have_vmx (void) 1.79 +{ 1.80 + if (!initialized) 1.81 + { 1.82 + int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; 1.83 + size_t length = sizeof(have_vmx); 1.84 + int error = 1.85 + sysctl (mib, 2, &have_vmx, &length, NULL, 0); 1.86 + 1.87 + if (error != 0) 1.88 + have_vmx = FALSE; 1.89 + 1.90 + initialized = TRUE; 1.91 + } 1.92 + return have_vmx; 1.93 +} 1.94 + 1.95 +#elif defined (__linux__) 1.96 +#include <sys/types.h> 1.97 +#include <sys/stat.h> 1.98 +#include <fcntl.h> 1.99 +#include <unistd.h> 1.100 +#include <stdio.h> 1.101 +#include <linux/auxvec.h> 1.102 +#include <asm/cputable.h> 1.103 + 1.104 +static pixman_bool_t 1.105 +pixman_have_vmx (void) 1.106 +{ 1.107 + if (!initialized) 1.108 + { 1.109 + char fname[64]; 1.110 + unsigned long buf[64]; 1.111 + ssize_t count = 0; 1.112 + pid_t pid; 1.113 + int fd, i; 1.114 + 1.115 + pid = getpid (); 1.116 + snprintf (fname, sizeof(fname) - 1, "/proc/%d/auxv", pid); 1.117 + 1.118 + fd = open (fname, O_RDONLY); 1.119 + if (fd >= 0) 1.120 + { 1.121 + for (i = 0; i <= (count / sizeof(unsigned long)); i += 2) 1.122 + { 1.123 + /* Read more if buf is empty... */ 1.124 + if (i == (count / sizeof(unsigned long))) 1.125 + { 1.126 + count = read (fd, buf, sizeof(buf)); 1.127 + if (count <= 0) 1.128 + break; 1.129 + i = 0; 1.130 + } 1.131 + 1.132 + if (buf[i] == AT_HWCAP) 1.133 + { 1.134 + have_vmx = !!(buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC); 1.135 + initialized = TRUE; 1.136 + break; 1.137 + } 1.138 + else if (buf[i] == AT_NULL) 1.139 + { 1.140 + break; 1.141 + } 1.142 + } 1.143 + close (fd); 1.144 + } 1.145 + } 1.146 + if (!initialized) 1.147 + { 1.148 + /* Something went wrong. Assume 'no' rather than playing 1.149 + fragile tricks with catching SIGILL. */ 1.150 + have_vmx = FALSE; 1.151 + initialized = TRUE; 1.152 + } 1.153 + 1.154 + return have_vmx; 1.155 +} 1.156 + 1.157 +#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ 1.158 +#include <signal.h> 1.159 +#include <setjmp.h> 1.160 + 1.161 +static jmp_buf jump_env; 1.162 + 1.163 +static void 1.164 +vmx_test (int sig, 1.165 + siginfo_t *si, 1.166 + void * unused) 1.167 +{ 1.168 + longjmp (jump_env, 1); 1.169 +} 1.170 + 1.171 +static pixman_bool_t 1.172 +pixman_have_vmx (void) 1.173 +{ 1.174 + struct sigaction sa, osa; 1.175 + int jmp_result; 1.176 + 1.177 + if (!initialized) 1.178 + { 1.179 + sa.sa_flags = SA_SIGINFO; 1.180 + sigemptyset (&sa.sa_mask); 1.181 + sa.sa_sigaction = vmx_test; 1.182 + sigaction (SIGILL, &sa, &osa); 1.183 + jmp_result = setjmp (jump_env); 1.184 + if (jmp_result == 0) 1.185 + { 1.186 + asm volatile ( "vor 0, 0, 0" ); 1.187 + } 1.188 + sigaction (SIGILL, &osa, NULL); 1.189 + have_vmx = (jmp_result == 0); 1.190 + initialized = TRUE; 1.191 + } 1.192 + return have_vmx; 1.193 +} 1.194 + 1.195 +#endif /* __APPLE__ */ 1.196 +#endif /* USE_VMX */ 1.197 + 1.198 +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) 1.199 + 1.200 +#if defined(_MSC_VER) 1.201 + 1.202 +#if defined(USE_ARM_SIMD) 1.203 +extern int pixman_msvc_try_arm_simd_op (); 1.204 + 1.205 +pixman_bool_t 1.206 +pixman_have_arm_simd (void) 1.207 +{ 1.208 + static pixman_bool_t initialized = FALSE; 1.209 + static pixman_bool_t have_arm_simd = FALSE; 1.210 + 1.211 + if (!initialized) 1.212 + { 1.213 + __try { 1.214 + pixman_msvc_try_arm_simd_op (); 1.215 + have_arm_simd = TRUE; 1.216 + } __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { 1.217 + have_arm_simd = FALSE; 1.218 + } 1.219 + initialized = TRUE; 1.220 + } 1.221 + 1.222 + return have_arm_simd; 1.223 +} 1.224 + 1.225 +#endif /* USE_ARM_SIMD */ 1.226 + 1.227 +#if defined(USE_ARM_NEON) 1.228 +extern int pixman_msvc_try_arm_neon_op (); 1.229 + 1.230 +pixman_bool_t 1.231 +pixman_have_arm_neon (void) 1.232 +{ 1.233 + static pixman_bool_t initialized = FALSE; 1.234 + static pixman_bool_t have_arm_neon = FALSE; 1.235 + 1.236 + if (!initialized) 1.237 + { 1.238 + __try 1.239 + { 1.240 + pixman_msvc_try_arm_neon_op (); 1.241 + have_arm_neon = TRUE; 1.242 + } 1.243 + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) 1.244 + { 1.245 + have_arm_neon = FALSE; 1.246 + } 1.247 + initialized = TRUE; 1.248 + } 1.249 + 1.250 + return have_arm_neon; 1.251 +} 1.252 + 1.253 +#endif /* USE_ARM_NEON */ 1.254 + 1.255 +#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */ 1.256 + 1.257 +/* Detection of ARM NEON on iOS is fairly simple because iOS binaries 1.258 + * contain separate executable images for each processor architecture. 1.259 + * So all we have to do is detect the armv7 architecture build. The 1.260 + * operating system automatically runs the armv7 binary for armv7 devices 1.261 + * and the armv6 binary for armv6 devices. 1.262 + */ 1.263 + 1.264 +pixman_bool_t 1.265 +pixman_have_arm_simd (void) 1.266 +{ 1.267 +#if defined(USE_ARM_SIMD) 1.268 + return TRUE; 1.269 +#else 1.270 + return FALSE; 1.271 +#endif 1.272 +} 1.273 + 1.274 +pixman_bool_t 1.275 +pixman_have_arm_neon (void) 1.276 +{ 1.277 +#if defined(USE_ARM_NEON) && defined(__ARM_NEON__) 1.278 + /* This is an armv7 cpu build */ 1.279 + return TRUE; 1.280 +#else 1.281 + /* This is an armv6 cpu build */ 1.282 + return FALSE; 1.283 +#endif 1.284 +} 1.285 + 1.286 +pixman_bool_t 1.287 +pixman_have_arm_iwmmxt (void) 1.288 +{ 1.289 +#if defined(USE_ARM_IWMMXT) 1.290 + return FALSE; 1.291 +#else 1.292 + return FALSE; 1.293 +#endif 1.294 +} 1.295 + 1.296 +#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */ 1.297 + 1.298 +static pixman_bool_t arm_has_v7 = FALSE; 1.299 +static pixman_bool_t arm_has_v6 = FALSE; 1.300 +static pixman_bool_t arm_has_vfp = FALSE; 1.301 +static pixman_bool_t arm_has_neon = FALSE; 1.302 +static pixman_bool_t arm_has_iwmmxt = FALSE; 1.303 +static pixman_bool_t arm_tests_initialized = FALSE; 1.304 + 1.305 +#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */ 1.306 + 1.307 +static void 1.308 +pixman_arm_read_auxv_or_cpu_features () 1.309 +{ 1.310 + char buf[1024]; 1.311 + char* pos; 1.312 + const char* ver_token = "CPU architecture: "; 1.313 + FILE* f = fopen("/proc/cpuinfo", "r"); 1.314 + if (!f) { 1.315 + arm_tests_initialized = TRUE; 1.316 + return; 1.317 + } 1.318 + 1.319 + fread(buf, sizeof(char), sizeof(buf), f); 1.320 + fclose(f); 1.321 + pos = strstr(buf, ver_token); 1.322 + if (pos) { 1.323 + char vchar = *(pos + strlen(ver_token)); 1.324 + if (vchar >= '0' && vchar <= '9') { 1.325 + int ver = vchar - '0'; 1.326 + arm_has_v7 = ver >= 7; 1.327 + arm_has_v6 = ver >= 6; 1.328 + } 1.329 + } 1.330 + arm_has_neon = strstr(buf, "neon") != NULL; 1.331 + arm_has_vfp = strstr(buf, "vfp") != NULL; 1.332 + arm_has_iwmmxt = strstr(buf, "iwmmxt") != NULL; 1.333 + arm_tests_initialized = TRUE; 1.334 +} 1.335 + 1.336 +#elif defined (__linux__) /* linux ELF */ 1.337 + 1.338 +#include <unistd.h> 1.339 +#include <sys/types.h> 1.340 +#include <sys/stat.h> 1.341 +#include <sys/mman.h> 1.342 +#include <fcntl.h> 1.343 +#include <string.h> 1.344 +#include <elf.h> 1.345 + 1.346 +static void 1.347 +pixman_arm_read_auxv_or_cpu_features () 1.348 +{ 1.349 + int fd; 1.350 + Elf32_auxv_t aux; 1.351 + 1.352 + fd = open ("/proc/self/auxv", O_RDONLY); 1.353 + if (fd >= 0) 1.354 + { 1.355 + while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) 1.356 + { 1.357 + if (aux.a_type == AT_HWCAP) 1.358 + { 1.359 + uint32_t hwcap = aux.a_un.a_val; 1.360 + /* hardcode these values to avoid depending on specific 1.361 + * versions of the hwcap header, e.g. HWCAP_NEON 1.362 + */ 1.363 + arm_has_vfp = (hwcap & 64) != 0; 1.364 + arm_has_iwmmxt = (hwcap & 512) != 0; 1.365 + /* this flag is only present on kernel 2.6.29 */ 1.366 + arm_has_neon = (hwcap & 4096) != 0; 1.367 + } 1.368 + else if (aux.a_type == AT_PLATFORM) 1.369 + { 1.370 + const char *plat = (const char*) aux.a_un.a_val; 1.371 + if (strncmp (plat, "v7l", 3) == 0) 1.372 + { 1.373 + arm_has_v7 = TRUE; 1.374 + arm_has_v6 = TRUE; 1.375 + } 1.376 + else if (strncmp (plat, "v6l", 3) == 0) 1.377 + { 1.378 + arm_has_v6 = TRUE; 1.379 + } 1.380 + } 1.381 + } 1.382 + close (fd); 1.383 + } 1.384 + 1.385 + arm_tests_initialized = TRUE; 1.386 +} 1.387 + 1.388 +#endif /* Linux elf */ 1.389 + 1.390 +#if defined(USE_ARM_SIMD) 1.391 +pixman_bool_t 1.392 +pixman_have_arm_simd (void) 1.393 +{ 1.394 + if (!arm_tests_initialized) 1.395 + pixman_arm_read_auxv_or_cpu_features (); 1.396 + 1.397 + return arm_has_v6; 1.398 +} 1.399 + 1.400 +#endif /* USE_ARM_SIMD */ 1.401 + 1.402 +#if defined(USE_ARM_NEON) 1.403 +pixman_bool_t 1.404 +pixman_have_arm_neon (void) 1.405 +{ 1.406 + if (!arm_tests_initialized) 1.407 + pixman_arm_read_auxv_or_cpu_features (); 1.408 + 1.409 + return arm_has_neon; 1.410 +} 1.411 + 1.412 +#endif /* USE_ARM_NEON */ 1.413 + 1.414 +#if defined(USE_ARM_IWMMXT) 1.415 +pixman_bool_t 1.416 +pixman_have_arm_iwmmxt (void) 1.417 +{ 1.418 + if (!arm_tests_initialized) 1.419 + pixman_arm_read_auxv_or_cpu_features (); 1.420 + 1.421 + return arm_has_iwmmxt; 1.422 +} 1.423 + 1.424 +#endif /* USE_ARM_IWMMXT */ 1.425 + 1.426 +#else /* !_MSC_VER && !Linux elf && !Android */ 1.427 + 1.428 +#define pixman_have_arm_simd() FALSE 1.429 +#define pixman_have_arm_neon() FALSE 1.430 +#define pixman_have_arm_iwmmxt() FALSE 1.431 + 1.432 +#endif 1.433 + 1.434 +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ 1.435 + 1.436 +#if defined(USE_MIPS_DSPR2) 1.437 + 1.438 +#if defined (__linux__) /* linux ELF */ 1.439 + 1.440 +pixman_bool_t 1.441 +pixman_have_mips_dspr2 (void) 1.442 +{ 1.443 + const char *search_string = "MIPS 74K"; 1.444 + const char *file_name = "/proc/cpuinfo"; 1.445 + /* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux. 1.446 + * It is based on /proc/cpuinfo, which reveals hardware configuration 1.447 + * to user-space applications. According to MIPS (early 2010), no similar 1.448 + * facility is universally available on the MIPS architectures, so it's up 1.449 + * to individual OSes to provide such. 1.450 + * 1.451 + * Only currently available MIPS core that supports DSPr2 is 74K. 1.452 + */ 1.453 + 1.454 + char cpuinfo_line[256]; 1.455 + 1.456 + FILE *f = NULL; 1.457 + 1.458 + if ((f = fopen (file_name, "r")) == NULL) 1.459 + return FALSE; 1.460 + 1.461 + while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL) 1.462 + { 1.463 + if (strstr (cpuinfo_line, search_string) != NULL) 1.464 + { 1.465 + fclose (f); 1.466 + return TRUE; 1.467 + } 1.468 + } 1.469 + 1.470 + fclose (f); 1.471 + 1.472 + /* Did not find string in the proc file. */ 1.473 + return FALSE; 1.474 +} 1.475 + 1.476 +#else /* linux ELF */ 1.477 + 1.478 +#define pixman_have_mips_dspr2() FALSE 1.479 + 1.480 +#endif /* linux ELF */ 1.481 + 1.482 +#endif /* USE_MIPS_DSPR2 */ 1.483 + 1.484 +#if defined(USE_X86_MMX) || defined(USE_SSE2) 1.485 +/* The CPU detection code needs to be in a file not compiled with 1.486 + * "-mmmx -msse", as gcc would generate CMOV instructions otherwise 1.487 + * that would lead to SIGILL instructions on old CPUs that don't have 1.488 + * it. 1.489 + */ 1.490 +#if !defined(__amd64__) && !defined(__x86_64__) && !defined(_M_AMD64) 1.491 + 1.492 +#ifdef HAVE_GETISAX 1.493 +#include <sys/auxv.h> 1.494 +#endif 1.495 + 1.496 +typedef enum 1.497 +{ 1.498 + NO_FEATURES = 0, 1.499 + MMX = 0x1, 1.500 + MMX_EXTENSIONS = 0x2, 1.501 + SSE = 0x6, 1.502 + SSE2 = 0x8, 1.503 + CMOV = 0x10 1.504 +} cpu_features_t; 1.505 + 1.506 + 1.507 +static unsigned int 1.508 +detect_cpu_features (void) 1.509 +{ 1.510 + unsigned int features = 0; 1.511 + unsigned int result = 0; 1.512 + 1.513 +#ifdef HAVE_GETISAX 1.514 + if (getisax (&result, 1)) 1.515 + { 1.516 + if (result & AV_386_CMOV) 1.517 + features |= CMOV; 1.518 + if (result & AV_386_MMX) 1.519 + features |= MMX; 1.520 + if (result & AV_386_AMD_MMX) 1.521 + features |= MMX_EXTENSIONS; 1.522 + if (result & AV_386_SSE) 1.523 + features |= SSE; 1.524 + if (result & AV_386_SSE2) 1.525 + features |= SSE2; 1.526 + } 1.527 +#else 1.528 + char vendor[13]; 1.529 +#ifdef _MSC_VER 1.530 + int vendor0 = 0, vendor1, vendor2; 1.531 +#endif 1.532 + vendor[0] = 0; 1.533 + vendor[12] = 0; 1.534 + 1.535 +#ifdef __GNUC__ 1.536 + /* see p. 118 of amd64 instruction set manual Vol3 */ 1.537 + /* We need to be careful about the handling of %ebx and 1.538 + * %esp here. We can't declare either one as clobbered 1.539 + * since they are special registers (%ebx is the "PIC 1.540 + * register" holding an offset to global data, %esp the 1.541 + * stack pointer), so we need to make sure they have their 1.542 + * original values when we access the output operands. 1.543 + */ 1.544 + __asm__ ( 1.545 + "pushf\n" 1.546 + "pop %%eax\n" 1.547 + "mov %%eax, %%ecx\n" 1.548 + "xor $0x00200000, %%eax\n" 1.549 + "push %%eax\n" 1.550 + "popf\n" 1.551 + "pushf\n" 1.552 + "pop %%eax\n" 1.553 + "mov $0x0, %%edx\n" 1.554 + "xor %%ecx, %%eax\n" 1.555 + "jz 1f\n" 1.556 + 1.557 + "mov $0x00000000, %%eax\n" 1.558 + "push %%ebx\n" 1.559 + "cpuid\n" 1.560 + "mov %%ebx, %%eax\n" 1.561 + "pop %%ebx\n" 1.562 + "mov %%eax, %1\n" 1.563 + "mov %%edx, %2\n" 1.564 + "mov %%ecx, %3\n" 1.565 + "mov $0x00000001, %%eax\n" 1.566 + "push %%ebx\n" 1.567 + "cpuid\n" 1.568 + "pop %%ebx\n" 1.569 + "1:\n" 1.570 + "mov %%edx, %0\n" 1.571 + : "=r" (result), 1.572 + "=m" (vendor[0]), 1.573 + "=m" (vendor[4]), 1.574 + "=m" (vendor[8]) 1.575 + : 1.576 + : "%eax", "%ecx", "%edx" 1.577 + ); 1.578 + 1.579 +#elif defined (_MSC_VER) 1.580 + 1.581 + _asm { 1.582 + pushfd 1.583 + pop eax 1.584 + mov ecx, eax 1.585 + xor eax, 00200000h 1.586 + push eax 1.587 + popfd 1.588 + pushfd 1.589 + pop eax 1.590 + mov edx, 0 1.591 + xor eax, ecx 1.592 + jz nocpuid 1.593 + 1.594 + mov eax, 0 1.595 + push ebx 1.596 + cpuid 1.597 + mov eax, ebx 1.598 + pop ebx 1.599 + mov vendor0, eax 1.600 + mov vendor1, edx 1.601 + mov vendor2, ecx 1.602 + mov eax, 1 1.603 + push ebx 1.604 + cpuid 1.605 + pop ebx 1.606 + nocpuid: 1.607 + mov result, edx 1.608 + } 1.609 + memmove (vendor + 0, &vendor0, 4); 1.610 + memmove (vendor + 4, &vendor1, 4); 1.611 + memmove (vendor + 8, &vendor2, 4); 1.612 + 1.613 +#else 1.614 +# error unsupported compiler 1.615 +#endif 1.616 + 1.617 + features = 0; 1.618 + if (result) 1.619 + { 1.620 + /* result now contains the standard feature bits */ 1.621 + if (result & (1 << 15)) 1.622 + features |= CMOV; 1.623 + if (result & (1 << 23)) 1.624 + features |= MMX; 1.625 + if (result & (1 << 25)) 1.626 + features |= SSE; 1.627 + if (result & (1 << 26)) 1.628 + features |= SSE2; 1.629 + if ((features & MMX) && !(features & SSE) && 1.630 + (strcmp (vendor, "AuthenticAMD") == 0 || 1.631 + strcmp (vendor, "Geode by NSC") == 0)) 1.632 + { 1.633 + /* check for AMD MMX extensions */ 1.634 +#ifdef __GNUC__ 1.635 + __asm__ ( 1.636 + " push %%ebx\n" 1.637 + " mov $0x80000000, %%eax\n" 1.638 + " cpuid\n" 1.639 + " xor %%edx, %%edx\n" 1.640 + " cmp $0x1, %%eax\n" 1.641 + " jge 2f\n" 1.642 + " mov $0x80000001, %%eax\n" 1.643 + " cpuid\n" 1.644 + "2:\n" 1.645 + " pop %%ebx\n" 1.646 + " mov %%edx, %0\n" 1.647 + : "=r" (result) 1.648 + : 1.649 + : "%eax", "%ecx", "%edx" 1.650 + ); 1.651 +#elif defined _MSC_VER 1.652 + _asm { 1.653 + push ebx 1.654 + mov eax, 80000000h 1.655 + cpuid 1.656 + xor edx, edx 1.657 + cmp eax, 1 1.658 + jge notamd 1.659 + mov eax, 80000001h 1.660 + cpuid 1.661 + notamd: 1.662 + pop ebx 1.663 + mov result, edx 1.664 + } 1.665 +#endif 1.666 + if (result & (1 << 22)) 1.667 + features |= MMX_EXTENSIONS; 1.668 + } 1.669 + } 1.670 +#endif /* HAVE_GETISAX */ 1.671 + 1.672 + return features; 1.673 +} 1.674 + 1.675 +#ifdef USE_X86_MMX 1.676 +static pixman_bool_t 1.677 +pixman_have_mmx (void) 1.678 +{ 1.679 + static pixman_bool_t initialized = FALSE; 1.680 + static pixman_bool_t mmx_present; 1.681 + 1.682 + if (!initialized) 1.683 + { 1.684 + unsigned int features = detect_cpu_features (); 1.685 + mmx_present = (features & (MMX | MMX_EXTENSIONS)) == (MMX | MMX_EXTENSIONS); 1.686 + initialized = TRUE; 1.687 + } 1.688 + 1.689 + return mmx_present; 1.690 +} 1.691 +#endif 1.692 + 1.693 +#ifdef USE_SSE2 1.694 +static pixman_bool_t 1.695 +pixman_have_sse2 (void) 1.696 +{ 1.697 + static pixman_bool_t initialized = FALSE; 1.698 + static pixman_bool_t sse2_present; 1.699 + 1.700 + if (!initialized) 1.701 + { 1.702 + unsigned int features = detect_cpu_features (); 1.703 + sse2_present = (features & (MMX | MMX_EXTENSIONS | SSE | SSE2)) == (MMX | MMX_EXTENSIONS | SSE | SSE2); 1.704 + initialized = TRUE; 1.705 + } 1.706 + 1.707 + return sse2_present; 1.708 +} 1.709 + 1.710 +#endif 1.711 + 1.712 +#else /* __amd64__ */ 1.713 +#ifdef USE_X86_MMX 1.714 +#define pixman_have_mmx() TRUE 1.715 +#endif 1.716 +#ifdef USE_SSE2 1.717 +#define pixman_have_sse2() TRUE 1.718 +#endif 1.719 +#endif /* __amd64__ */ 1.720 +#endif 1.721 + 1.722 +static pixman_bool_t 1.723 +disabled (const char *name) 1.724 +{ 1.725 + const char *env; 1.726 + 1.727 + if ((env = getenv ("PIXMAN_DISABLE"))) 1.728 + { 1.729 + do 1.730 + { 1.731 + const char *end; 1.732 + int len; 1.733 + 1.734 + if ((end = strchr (env, ' '))) 1.735 + len = end - env; 1.736 + else 1.737 + len = strlen (env); 1.738 + 1.739 + if (strlen (name) == len && strncmp (name, env, len) == 0) 1.740 + { 1.741 + printf ("pixman: Disabled %s implementation\n", name); 1.742 + return TRUE; 1.743 + } 1.744 + 1.745 + env += len; 1.746 + } 1.747 + while (*env++); 1.748 + } 1.749 + 1.750 + return FALSE; 1.751 +} 1.752 + 1.753 +pixman_implementation_t * 1.754 +_pixman_choose_implementation (void) 1.755 +{ 1.756 + pixman_implementation_t *imp; 1.757 + 1.758 + imp = _pixman_implementation_create_general(); 1.759 + 1.760 + if (!disabled ("fast")) 1.761 + imp = _pixman_implementation_create_fast_path (imp); 1.762 + 1.763 +#ifdef USE_X86_MMX 1.764 + if (!disabled ("mmx") && pixman_have_mmx ()) 1.765 + imp = _pixman_implementation_create_mmx (imp); 1.766 +#endif 1.767 + 1.768 +#ifdef USE_SSE2 1.769 + if (!disabled ("sse2") && pixman_have_sse2 ()) 1.770 + imp = _pixman_implementation_create_sse2 (imp); 1.771 +#endif 1.772 + 1.773 +#ifdef USE_ARM_SIMD 1.774 + if (!disabled ("arm-simd") && pixman_have_arm_simd ()) 1.775 + imp = _pixman_implementation_create_arm_simd (imp); 1.776 +#endif 1.777 + 1.778 +#ifdef USE_ARM_IWMMXT 1.779 + if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ()) 1.780 + imp = _pixman_implementation_create_mmx (imp); 1.781 +#endif 1.782 + 1.783 +#ifdef USE_ARM_NEON 1.784 + if (!disabled ("arm-neon") && pixman_have_arm_neon ()) 1.785 + imp = _pixman_implementation_create_arm_neon (imp); 1.786 +#endif 1.787 + 1.788 +#ifdef USE_MIPS_DSPR2 1.789 + if (!disabled ("mips-dspr2") && pixman_have_mips_dspr2 ()) 1.790 + imp = _pixman_implementation_create_mips_dspr2 (imp); 1.791 +#endif 1.792 + 1.793 +#ifdef USE_VMX 1.794 + if (!disabled ("vmx") && pixman_have_vmx ()) 1.795 + imp = _pixman_implementation_create_vmx (imp); 1.796 +#endif 1.797 + 1.798 + imp = _pixman_implementation_create_noop (imp); 1.799 + 1.800 + return imp; 1.801 +} 1.802 +