michael@0: /* michael@0: * Copyright © 2000 SuSE, Inc. michael@0: * Copyright © 2007 Red Hat, Inc. michael@0: * michael@0: * Permission to use, copy, modify, distribute, and sell this software and its michael@0: * documentation for any purpose is hereby granted without fee, provided that michael@0: * the above copyright notice appear in all copies and that both that michael@0: * copyright notice and this permission notice appear in supporting michael@0: * documentation, and that the name of SuSE not be used in advertising or michael@0: * publicity pertaining to distribution of the software without specific, michael@0: * written prior permission. SuSE makes no representations about the michael@0: * suitability of this software for any purpose. It is provided "as is" michael@0: * without express or implied warranty. michael@0: * michael@0: * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL michael@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE michael@0: * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES michael@0: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION michael@0: * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN michael@0: * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. michael@0: */ michael@0: #ifdef HAVE_CONFIG_H michael@0: #include michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #if defined(USE_ARM_SIMD) && defined(_MSC_VER) michael@0: /* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(__APPLE__) michael@0: #include "TargetConditionals.h" michael@0: #endif michael@0: michael@0: #include "pixman-private.h" michael@0: michael@0: #ifdef USE_VMX michael@0: michael@0: /* The CPU detection code needs to be in a file not compiled with michael@0: * "-maltivec -mabi=altivec", as gcc would try to save vector register michael@0: * across function calls causing SIGILL on cpus without Altivec/vmx. michael@0: */ michael@0: static pixman_bool_t initialized = FALSE; michael@0: static volatile pixman_bool_t have_vmx = TRUE; michael@0: michael@0: #ifdef __APPLE__ michael@0: #include michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: if (!initialized) michael@0: { michael@0: size_t length = sizeof(have_vmx); michael@0: int error = michael@0: sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0); michael@0: michael@0: if (error) michael@0: have_vmx = FALSE; michael@0: michael@0: initialized = TRUE; michael@0: } michael@0: return have_vmx; michael@0: } michael@0: michael@0: #elif defined (__OpenBSD__) michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: if (!initialized) michael@0: { michael@0: int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; michael@0: size_t length = sizeof(have_vmx); michael@0: int error = michael@0: sysctl (mib, 2, &have_vmx, &length, NULL, 0); michael@0: michael@0: if (error != 0) michael@0: have_vmx = FALSE; michael@0: michael@0: initialized = TRUE; michael@0: } michael@0: return have_vmx; michael@0: } michael@0: michael@0: #elif defined (__linux__) michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: if (!initialized) michael@0: { michael@0: char fname[64]; michael@0: unsigned long buf[64]; michael@0: ssize_t count = 0; michael@0: pid_t pid; michael@0: int fd, i; michael@0: michael@0: pid = getpid (); michael@0: snprintf (fname, sizeof(fname) - 1, "/proc/%d/auxv", pid); michael@0: michael@0: fd = open (fname, O_RDONLY); michael@0: if (fd >= 0) michael@0: { michael@0: for (i = 0; i <= (count / sizeof(unsigned long)); i += 2) michael@0: { michael@0: /* Read more if buf is empty... */ michael@0: if (i == (count / sizeof(unsigned long))) michael@0: { michael@0: count = read (fd, buf, sizeof(buf)); michael@0: if (count <= 0) michael@0: break; michael@0: i = 0; michael@0: } michael@0: michael@0: if (buf[i] == AT_HWCAP) michael@0: { michael@0: have_vmx = !!(buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC); michael@0: initialized = TRUE; michael@0: break; michael@0: } michael@0: else if (buf[i] == AT_NULL) michael@0: { michael@0: break; michael@0: } michael@0: } michael@0: close (fd); michael@0: } michael@0: } michael@0: if (!initialized) michael@0: { michael@0: /* Something went wrong. Assume 'no' rather than playing michael@0: fragile tricks with catching SIGILL. */ michael@0: have_vmx = FALSE; michael@0: initialized = TRUE; michael@0: } michael@0: michael@0: return have_vmx; michael@0: } michael@0: michael@0: #else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ michael@0: #include michael@0: #include michael@0: michael@0: static jmp_buf jump_env; michael@0: michael@0: static void michael@0: vmx_test (int sig, michael@0: siginfo_t *si, michael@0: void * unused) michael@0: { michael@0: longjmp (jump_env, 1); michael@0: } michael@0: michael@0: static pixman_bool_t michael@0: pixman_have_vmx (void) michael@0: { michael@0: struct sigaction sa, osa; michael@0: int jmp_result; michael@0: michael@0: if (!initialized) michael@0: { michael@0: sa.sa_flags = SA_SIGINFO; michael@0: sigemptyset (&sa.sa_mask); michael@0: sa.sa_sigaction = vmx_test; michael@0: sigaction (SIGILL, &sa, &osa); michael@0: jmp_result = setjmp (jump_env); michael@0: if (jmp_result == 0) michael@0: { michael@0: asm volatile ( "vor 0, 0, 0" ); michael@0: } michael@0: sigaction (SIGILL, &osa, NULL); michael@0: have_vmx = (jmp_result == 0); michael@0: initialized = TRUE; michael@0: } michael@0: return have_vmx; michael@0: } michael@0: michael@0: #endif /* __APPLE__ */ michael@0: #endif /* USE_VMX */ michael@0: michael@0: #if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) michael@0: michael@0: #if defined(_MSC_VER) michael@0: michael@0: #if defined(USE_ARM_SIMD) michael@0: extern int pixman_msvc_try_arm_simd_op (); michael@0: michael@0: pixman_bool_t michael@0: pixman_have_arm_simd (void) michael@0: { michael@0: static pixman_bool_t initialized = FALSE; michael@0: static pixman_bool_t have_arm_simd = FALSE; michael@0: michael@0: if (!initialized) michael@0: { michael@0: __try { michael@0: pixman_msvc_try_arm_simd_op (); michael@0: have_arm_simd = TRUE; michael@0: } __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { michael@0: have_arm_simd = FALSE; michael@0: } michael@0: initialized = TRUE; michael@0: } michael@0: michael@0: return have_arm_simd; michael@0: } michael@0: michael@0: #endif /* USE_ARM_SIMD */ michael@0: michael@0: #if defined(USE_ARM_NEON) michael@0: extern int pixman_msvc_try_arm_neon_op (); michael@0: michael@0: pixman_bool_t michael@0: pixman_have_arm_neon (void) michael@0: { michael@0: static pixman_bool_t initialized = FALSE; michael@0: static pixman_bool_t have_arm_neon = FALSE; michael@0: michael@0: if (!initialized) michael@0: { michael@0: __try michael@0: { michael@0: pixman_msvc_try_arm_neon_op (); michael@0: have_arm_neon = TRUE; michael@0: } michael@0: __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) michael@0: { michael@0: have_arm_neon = FALSE; michael@0: } michael@0: initialized = TRUE; michael@0: } michael@0: michael@0: return have_arm_neon; michael@0: } michael@0: michael@0: #endif /* USE_ARM_NEON */ michael@0: michael@0: #elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */ michael@0: michael@0: /* Detection of ARM NEON on iOS is fairly simple because iOS binaries michael@0: * contain separate executable images for each processor architecture. michael@0: * So all we have to do is detect the armv7 architecture build. The michael@0: * operating system automatically runs the armv7 binary for armv7 devices michael@0: * and the armv6 binary for armv6 devices. michael@0: */ michael@0: michael@0: pixman_bool_t michael@0: pixman_have_arm_simd (void) michael@0: { michael@0: #if defined(USE_ARM_SIMD) michael@0: return TRUE; michael@0: #else michael@0: return FALSE; michael@0: #endif michael@0: } michael@0: michael@0: pixman_bool_t michael@0: pixman_have_arm_neon (void) michael@0: { michael@0: #if defined(USE_ARM_NEON) && defined(__ARM_NEON__) michael@0: /* This is an armv7 cpu build */ michael@0: return TRUE; michael@0: #else michael@0: /* This is an armv6 cpu build */ michael@0: return FALSE; michael@0: #endif michael@0: } michael@0: michael@0: pixman_bool_t michael@0: pixman_have_arm_iwmmxt (void) michael@0: { michael@0: #if defined(USE_ARM_IWMMXT) michael@0: return FALSE; michael@0: #else michael@0: return FALSE; michael@0: #endif michael@0: } michael@0: michael@0: #elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */ michael@0: michael@0: static pixman_bool_t arm_has_v7 = FALSE; michael@0: static pixman_bool_t arm_has_v6 = FALSE; michael@0: static pixman_bool_t arm_has_vfp = FALSE; michael@0: static pixman_bool_t arm_has_neon = FALSE; michael@0: static pixman_bool_t arm_has_iwmmxt = FALSE; michael@0: static pixman_bool_t arm_tests_initialized = FALSE; michael@0: michael@0: #if defined(__ANDROID__) || defined(ANDROID) /* Android device support */ michael@0: michael@0: static void michael@0: pixman_arm_read_auxv_or_cpu_features () michael@0: { michael@0: char buf[1024]; michael@0: char* pos; michael@0: const char* ver_token = "CPU architecture: "; michael@0: FILE* f = fopen("/proc/cpuinfo", "r"); michael@0: if (!f) { michael@0: arm_tests_initialized = TRUE; michael@0: return; michael@0: } michael@0: michael@0: fread(buf, sizeof(char), sizeof(buf), f); michael@0: fclose(f); michael@0: pos = strstr(buf, ver_token); michael@0: if (pos) { michael@0: char vchar = *(pos + strlen(ver_token)); michael@0: if (vchar >= '0' && vchar <= '9') { michael@0: int ver = vchar - '0'; michael@0: arm_has_v7 = ver >= 7; michael@0: arm_has_v6 = ver >= 6; michael@0: } michael@0: } michael@0: arm_has_neon = strstr(buf, "neon") != NULL; michael@0: arm_has_vfp = strstr(buf, "vfp") != NULL; michael@0: arm_has_iwmmxt = strstr(buf, "iwmmxt") != NULL; michael@0: arm_tests_initialized = TRUE; michael@0: } michael@0: michael@0: #elif defined (__linux__) /* linux ELF */ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static void michael@0: pixman_arm_read_auxv_or_cpu_features () michael@0: { michael@0: int fd; michael@0: Elf32_auxv_t aux; michael@0: michael@0: fd = open ("/proc/self/auxv", O_RDONLY); michael@0: if (fd >= 0) michael@0: { michael@0: while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) michael@0: { michael@0: if (aux.a_type == AT_HWCAP) michael@0: { michael@0: uint32_t hwcap = aux.a_un.a_val; michael@0: /* hardcode these values to avoid depending on specific michael@0: * versions of the hwcap header, e.g. HWCAP_NEON michael@0: */ michael@0: arm_has_vfp = (hwcap & 64) != 0; michael@0: arm_has_iwmmxt = (hwcap & 512) != 0; michael@0: /* this flag is only present on kernel 2.6.29 */ michael@0: arm_has_neon = (hwcap & 4096) != 0; michael@0: } michael@0: else if (aux.a_type == AT_PLATFORM) michael@0: { michael@0: const char *plat = (const char*) aux.a_un.a_val; michael@0: if (strncmp (plat, "v7l", 3) == 0) michael@0: { michael@0: arm_has_v7 = TRUE; michael@0: arm_has_v6 = TRUE; michael@0: } michael@0: else if (strncmp (plat, "v6l", 3) == 0) michael@0: { michael@0: arm_has_v6 = TRUE; michael@0: } michael@0: } michael@0: } michael@0: close (fd); michael@0: } michael@0: michael@0: arm_tests_initialized = TRUE; michael@0: } michael@0: michael@0: #endif /* Linux elf */ michael@0: michael@0: #if defined(USE_ARM_SIMD) michael@0: pixman_bool_t michael@0: pixman_have_arm_simd (void) michael@0: { michael@0: if (!arm_tests_initialized) michael@0: pixman_arm_read_auxv_or_cpu_features (); michael@0: michael@0: return arm_has_v6; michael@0: } michael@0: michael@0: #endif /* USE_ARM_SIMD */ michael@0: michael@0: #if defined(USE_ARM_NEON) michael@0: pixman_bool_t michael@0: pixman_have_arm_neon (void) michael@0: { michael@0: if (!arm_tests_initialized) michael@0: pixman_arm_read_auxv_or_cpu_features (); michael@0: michael@0: return arm_has_neon; michael@0: } michael@0: michael@0: #endif /* USE_ARM_NEON */ michael@0: michael@0: #if defined(USE_ARM_IWMMXT) michael@0: pixman_bool_t michael@0: pixman_have_arm_iwmmxt (void) michael@0: { michael@0: if (!arm_tests_initialized) michael@0: pixman_arm_read_auxv_or_cpu_features (); michael@0: michael@0: return arm_has_iwmmxt; michael@0: } michael@0: michael@0: #endif /* USE_ARM_IWMMXT */ michael@0: michael@0: #else /* !_MSC_VER && !Linux elf && !Android */ michael@0: michael@0: #define pixman_have_arm_simd() FALSE michael@0: #define pixman_have_arm_neon() FALSE michael@0: #define pixman_have_arm_iwmmxt() FALSE michael@0: michael@0: #endif michael@0: michael@0: #endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ michael@0: michael@0: #if defined(USE_MIPS_DSPR2) michael@0: michael@0: #if defined (__linux__) /* linux ELF */ michael@0: michael@0: pixman_bool_t michael@0: pixman_have_mips_dspr2 (void) michael@0: { michael@0: const char *search_string = "MIPS 74K"; michael@0: const char *file_name = "/proc/cpuinfo"; michael@0: /* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux. michael@0: * It is based on /proc/cpuinfo, which reveals hardware configuration michael@0: * to user-space applications. According to MIPS (early 2010), no similar michael@0: * facility is universally available on the MIPS architectures, so it's up michael@0: * to individual OSes to provide such. michael@0: * michael@0: * Only currently available MIPS core that supports DSPr2 is 74K. michael@0: */ michael@0: michael@0: char cpuinfo_line[256]; michael@0: michael@0: FILE *f = NULL; michael@0: michael@0: if ((f = fopen (file_name, "r")) == NULL) michael@0: return FALSE; michael@0: michael@0: while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL) michael@0: { michael@0: if (strstr (cpuinfo_line, search_string) != NULL) michael@0: { michael@0: fclose (f); michael@0: return TRUE; michael@0: } michael@0: } michael@0: michael@0: fclose (f); michael@0: michael@0: /* Did not find string in the proc file. */ michael@0: return FALSE; michael@0: } michael@0: michael@0: #else /* linux ELF */ michael@0: michael@0: #define pixman_have_mips_dspr2() FALSE michael@0: michael@0: #endif /* linux ELF */ michael@0: michael@0: #endif /* USE_MIPS_DSPR2 */ michael@0: michael@0: #if defined(USE_X86_MMX) || defined(USE_SSE2) michael@0: /* The CPU detection code needs to be in a file not compiled with michael@0: * "-mmmx -msse", as gcc would generate CMOV instructions otherwise michael@0: * that would lead to SIGILL instructions on old CPUs that don't have michael@0: * it. michael@0: */ michael@0: #if !defined(__amd64__) && !defined(__x86_64__) && !defined(_M_AMD64) michael@0: michael@0: #ifdef HAVE_GETISAX michael@0: #include michael@0: #endif michael@0: michael@0: typedef enum michael@0: { michael@0: NO_FEATURES = 0, michael@0: MMX = 0x1, michael@0: MMX_EXTENSIONS = 0x2, michael@0: SSE = 0x6, michael@0: SSE2 = 0x8, michael@0: CMOV = 0x10 michael@0: } cpu_features_t; michael@0: michael@0: michael@0: static unsigned int michael@0: detect_cpu_features (void) michael@0: { michael@0: unsigned int features = 0; michael@0: unsigned int result = 0; michael@0: michael@0: #ifdef HAVE_GETISAX michael@0: if (getisax (&result, 1)) michael@0: { michael@0: if (result & AV_386_CMOV) michael@0: features |= CMOV; michael@0: if (result & AV_386_MMX) michael@0: features |= MMX; michael@0: if (result & AV_386_AMD_MMX) michael@0: features |= MMX_EXTENSIONS; michael@0: if (result & AV_386_SSE) michael@0: features |= SSE; michael@0: if (result & AV_386_SSE2) michael@0: features |= SSE2; michael@0: } michael@0: #else michael@0: char vendor[13]; michael@0: #ifdef _MSC_VER michael@0: int vendor0 = 0, vendor1, vendor2; michael@0: #endif michael@0: vendor[0] = 0; michael@0: vendor[12] = 0; michael@0: michael@0: #ifdef __GNUC__ michael@0: /* see p. 118 of amd64 instruction set manual Vol3 */ michael@0: /* We need to be careful about the handling of %ebx and michael@0: * %esp here. We can't declare either one as clobbered michael@0: * since they are special registers (%ebx is the "PIC michael@0: * register" holding an offset to global data, %esp the michael@0: * stack pointer), so we need to make sure they have their michael@0: * original values when we access the output operands. michael@0: */ michael@0: __asm__ ( michael@0: "pushf\n" michael@0: "pop %%eax\n" michael@0: "mov %%eax, %%ecx\n" michael@0: "xor $0x00200000, %%eax\n" michael@0: "push %%eax\n" michael@0: "popf\n" michael@0: "pushf\n" michael@0: "pop %%eax\n" michael@0: "mov $0x0, %%edx\n" michael@0: "xor %%ecx, %%eax\n" michael@0: "jz 1f\n" michael@0: michael@0: "mov $0x00000000, %%eax\n" michael@0: "push %%ebx\n" michael@0: "cpuid\n" michael@0: "mov %%ebx, %%eax\n" michael@0: "pop %%ebx\n" michael@0: "mov %%eax, %1\n" michael@0: "mov %%edx, %2\n" michael@0: "mov %%ecx, %3\n" michael@0: "mov $0x00000001, %%eax\n" michael@0: "push %%ebx\n" michael@0: "cpuid\n" michael@0: "pop %%ebx\n" michael@0: "1:\n" michael@0: "mov %%edx, %0\n" michael@0: : "=r" (result), michael@0: "=m" (vendor[0]), michael@0: "=m" (vendor[4]), michael@0: "=m" (vendor[8]) michael@0: : michael@0: : "%eax", "%ecx", "%edx" michael@0: ); michael@0: michael@0: #elif defined (_MSC_VER) michael@0: michael@0: _asm { michael@0: pushfd michael@0: pop eax michael@0: mov ecx, eax michael@0: xor eax, 00200000h michael@0: push eax michael@0: popfd michael@0: pushfd michael@0: pop eax michael@0: mov edx, 0 michael@0: xor eax, ecx michael@0: jz nocpuid michael@0: michael@0: mov eax, 0 michael@0: push ebx michael@0: cpuid michael@0: mov eax, ebx michael@0: pop ebx michael@0: mov vendor0, eax michael@0: mov vendor1, edx michael@0: mov vendor2, ecx michael@0: mov eax, 1 michael@0: push ebx michael@0: cpuid michael@0: pop ebx michael@0: nocpuid: michael@0: mov result, edx michael@0: } michael@0: memmove (vendor + 0, &vendor0, 4); michael@0: memmove (vendor + 4, &vendor1, 4); michael@0: memmove (vendor + 8, &vendor2, 4); michael@0: michael@0: #else michael@0: # error unsupported compiler michael@0: #endif michael@0: michael@0: features = 0; michael@0: if (result) michael@0: { michael@0: /* result now contains the standard feature bits */ michael@0: if (result & (1 << 15)) michael@0: features |= CMOV; michael@0: if (result & (1 << 23)) michael@0: features |= MMX; michael@0: if (result & (1 << 25)) michael@0: features |= SSE; michael@0: if (result & (1 << 26)) michael@0: features |= SSE2; michael@0: if ((features & MMX) && !(features & SSE) && michael@0: (strcmp (vendor, "AuthenticAMD") == 0 || michael@0: strcmp (vendor, "Geode by NSC") == 0)) michael@0: { michael@0: /* check for AMD MMX extensions */ michael@0: #ifdef __GNUC__ michael@0: __asm__ ( michael@0: " push %%ebx\n" michael@0: " mov $0x80000000, %%eax\n" michael@0: " cpuid\n" michael@0: " xor %%edx, %%edx\n" michael@0: " cmp $0x1, %%eax\n" michael@0: " jge 2f\n" michael@0: " mov $0x80000001, %%eax\n" michael@0: " cpuid\n" michael@0: "2:\n" michael@0: " pop %%ebx\n" michael@0: " mov %%edx, %0\n" michael@0: : "=r" (result) michael@0: : michael@0: : "%eax", "%ecx", "%edx" michael@0: ); michael@0: #elif defined _MSC_VER michael@0: _asm { michael@0: push ebx michael@0: mov eax, 80000000h michael@0: cpuid michael@0: xor edx, edx michael@0: cmp eax, 1 michael@0: jge notamd michael@0: mov eax, 80000001h michael@0: cpuid michael@0: notamd: michael@0: pop ebx michael@0: mov result, edx michael@0: } michael@0: #endif michael@0: if (result & (1 << 22)) michael@0: features |= MMX_EXTENSIONS; michael@0: } michael@0: } michael@0: #endif /* HAVE_GETISAX */ michael@0: michael@0: return features; michael@0: } michael@0: michael@0: #ifdef USE_X86_MMX michael@0: static pixman_bool_t michael@0: pixman_have_mmx (void) michael@0: { michael@0: static pixman_bool_t initialized = FALSE; michael@0: static pixman_bool_t mmx_present; michael@0: michael@0: if (!initialized) michael@0: { michael@0: unsigned int features = detect_cpu_features (); michael@0: mmx_present = (features & (MMX | MMX_EXTENSIONS)) == (MMX | MMX_EXTENSIONS); michael@0: initialized = TRUE; michael@0: } michael@0: michael@0: return mmx_present; michael@0: } michael@0: #endif michael@0: michael@0: #ifdef USE_SSE2 michael@0: static pixman_bool_t michael@0: pixman_have_sse2 (void) michael@0: { michael@0: static pixman_bool_t initialized = FALSE; michael@0: static pixman_bool_t sse2_present; michael@0: michael@0: if (!initialized) michael@0: { michael@0: unsigned int features = detect_cpu_features (); michael@0: sse2_present = (features & (MMX | MMX_EXTENSIONS | SSE | SSE2)) == (MMX | MMX_EXTENSIONS | SSE | SSE2); michael@0: initialized = TRUE; michael@0: } michael@0: michael@0: return sse2_present; michael@0: } michael@0: michael@0: #endif michael@0: michael@0: #else /* __amd64__ */ michael@0: #ifdef USE_X86_MMX michael@0: #define pixman_have_mmx() TRUE michael@0: #endif michael@0: #ifdef USE_SSE2 michael@0: #define pixman_have_sse2() TRUE michael@0: #endif michael@0: #endif /* __amd64__ */ michael@0: #endif michael@0: michael@0: static pixman_bool_t michael@0: disabled (const char *name) michael@0: { michael@0: const char *env; michael@0: michael@0: if ((env = getenv ("PIXMAN_DISABLE"))) michael@0: { michael@0: do michael@0: { michael@0: const char *end; michael@0: int len; michael@0: michael@0: if ((end = strchr (env, ' '))) michael@0: len = end - env; michael@0: else michael@0: len = strlen (env); michael@0: michael@0: if (strlen (name) == len && strncmp (name, env, len) == 0) michael@0: { michael@0: printf ("pixman: Disabled %s implementation\n", name); michael@0: return TRUE; michael@0: } michael@0: michael@0: env += len; michael@0: } michael@0: while (*env++); michael@0: } michael@0: michael@0: return FALSE; michael@0: } michael@0: michael@0: pixman_implementation_t * michael@0: _pixman_choose_implementation (void) michael@0: { michael@0: pixman_implementation_t *imp; michael@0: michael@0: imp = _pixman_implementation_create_general(); michael@0: michael@0: if (!disabled ("fast")) michael@0: imp = _pixman_implementation_create_fast_path (imp); michael@0: michael@0: #ifdef USE_X86_MMX michael@0: if (!disabled ("mmx") && pixman_have_mmx ()) michael@0: imp = _pixman_implementation_create_mmx (imp); michael@0: #endif michael@0: michael@0: #ifdef USE_SSE2 michael@0: if (!disabled ("sse2") && pixman_have_sse2 ()) michael@0: imp = _pixman_implementation_create_sse2 (imp); michael@0: #endif michael@0: michael@0: #ifdef USE_ARM_SIMD michael@0: if (!disabled ("arm-simd") && pixman_have_arm_simd ()) michael@0: imp = _pixman_implementation_create_arm_simd (imp); michael@0: #endif michael@0: michael@0: #ifdef USE_ARM_IWMMXT michael@0: if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ()) michael@0: imp = _pixman_implementation_create_mmx (imp); michael@0: #endif michael@0: michael@0: #ifdef USE_ARM_NEON michael@0: if (!disabled ("arm-neon") && pixman_have_arm_neon ()) michael@0: imp = _pixman_implementation_create_arm_neon (imp); michael@0: #endif michael@0: michael@0: #ifdef USE_MIPS_DSPR2 michael@0: if (!disabled ("mips-dspr2") && pixman_have_mips_dspr2 ()) michael@0: imp = _pixman_implementation_create_mips_dspr2 (imp); michael@0: #endif michael@0: michael@0: #ifdef USE_VMX michael@0: if (!disabled ("vmx") && pixman_have_vmx ()) michael@0: imp = _pixman_implementation_create_vmx (imp); michael@0: #endif michael@0: michael@0: imp = _pixman_implementation_create_noop (imp); michael@0: michael@0: return imp; michael@0: } michael@0: