From 8590415f0e54520a176ff0fb53deb82be16873dd Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Tue, 26 Jun 2012 17:02:24 -0400 Subject: [PATCH] Move ARM specific CPU detection to a new file pixman-arm.c Similar to the x86 commit, this moves the ARM specific CPU detection to its own file which exports a pixman_arm_get_implementations() function that is supposed to be a noop on non-ARM. --- pixman/Makefile.sources | 1 + pixman/pixman-arm.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ pixman/pixman-cpu.c | 254 +---------------------------------------- pixman/pixman-private.h | 3 + 4 files changed, 300 insertions(+), 253 deletions(-) create mode 100644 pixman/pixman-arm.c diff --git a/pixman/Makefile.sources b/pixman/Makefile.sources index 4e0137a..7f2b75f 100644 --- a/pixman/Makefile.sources +++ b/pixman/Makefile.sources @@ -8,6 +8,7 @@ libpixman_sources = \ pixman-conical-gradient.c \ pixman-cpu.c \ pixman-x86.c \ + pixman-arm.c \ pixman-edge.c \ pixman-edge-accessors.c \ pixman-fast-path.c \ diff --git a/pixman/pixman-arm.c b/pixman/pixman-arm.c new file mode 100644 index 0000000..6625d7f --- /dev/null +++ b/pixman/pixman-arm.c @@ -0,0 +1,295 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) + +#include +#include + +#if defined(USE_ARM_SIMD) && defined(_MSC_VER) +/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ +#include +#endif + +#if defined(__APPLE__) +#include "TargetConditionals.h" +#endif + +#if defined(_MSC_VER) + +#if defined(USE_ARM_SIMD) +extern int pixman_msvc_try_arm_simd_op (); + +pixman_bool_t +pixman_have_arm_simd (void) +{ + static pixman_bool_t initialized = FALSE; + static pixman_bool_t have_arm_simd = FALSE; + + if (!initialized) + { + __try { + pixman_msvc_try_arm_simd_op (); + have_arm_simd = TRUE; + } __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { + have_arm_simd = FALSE; + } + initialized = TRUE; + } + + return have_arm_simd; +} + +#endif /* USE_ARM_SIMD */ + +#if defined(USE_ARM_NEON) +extern int pixman_msvc_try_arm_neon_op (); + +pixman_bool_t +pixman_have_arm_neon (void) +{ + static pixman_bool_t initialized = FALSE; + static pixman_bool_t have_arm_neon = FALSE; + + if (!initialized) + { + __try + { + pixman_msvc_try_arm_neon_op (); + have_arm_neon = TRUE; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) + { + have_arm_neon = FALSE; + } + initialized = TRUE; + } + + return have_arm_neon; +} + +#endif /* USE_ARM_NEON */ + +#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */ + +/* Detection of ARM NEON on iOS is fairly simple because iOS binaries + * contain separate executable images for each processor architecture. + * So all we have to do is detect the armv7 architecture build. The + * operating system automatically runs the armv7 binary for armv7 devices + * and the armv6 binary for armv6 devices. + */ + +pixman_bool_t +pixman_have_arm_simd (void) +{ +#if defined(USE_ARM_SIMD) + return TRUE; +#else + return FALSE; +#endif +} + +pixman_bool_t +pixman_have_arm_neon (void) +{ +#if defined(USE_ARM_NEON) && defined(__ARM_NEON__) + /* This is an armv7 cpu build */ + return TRUE; +#else + /* This is an armv6 cpu build */ + return FALSE; +#endif +} + +pixman_bool_t +pixman_have_arm_iwmmxt (void) +{ +#if defined(USE_ARM_IWMMXT) + return FALSE; +#else + return FALSE; +#endif +} + +#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */ + +static pixman_bool_t arm_has_v7 = FALSE; +static pixman_bool_t arm_has_v6 = FALSE; +static pixman_bool_t arm_has_vfp = FALSE; +static pixman_bool_t arm_has_neon = FALSE; +static pixman_bool_t arm_has_iwmmxt = FALSE; +static pixman_bool_t arm_tests_initialized = FALSE; + +#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */ + +#include + +static void +pixman_arm_read_auxv_or_cpu_features () +{ + AndroidCpuFamily cpu_family; + uint64_t cpu_features; + + cpu_family = android_getCpuFamily(); + cpu_features = android_getCpuFeatures(); + + if (cpu_family == ANDROID_CPU_FAMILY_ARM) + { + if (cpu_features & ANDROID_CPU_ARM_FEATURE_ARMv7) + arm_has_v7 = TRUE; + + if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3) + arm_has_vfp = TRUE; + + if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) + arm_has_neon = TRUE; + } + + arm_tests_initialized = TRUE; +} + +#elif defined (__linux__) /* linux ELF */ + +#include +#include +#include +#include +#include +#include +#include + +static void +pixman_arm_read_auxv_or_cpu_features () +{ + int fd; + Elf32_auxv_t aux; + + fd = open ("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) + { + if (aux.a_type == AT_HWCAP) + { + uint32_t hwcap = aux.a_un.a_val; + /* hardcode these values to avoid depending on specific + * versions of the hwcap header, e.g. HWCAP_NEON + */ + arm_has_vfp = (hwcap & 64) != 0; + arm_has_iwmmxt = (hwcap & 512) != 0; + /* this flag is only present on kernel 2.6.29 */ + arm_has_neon = (hwcap & 4096) != 0; + } + else if (aux.a_type == AT_PLATFORM) + { + const char *plat = (const char*) aux.a_un.a_val; + if (strncmp (plat, "v7l", 3) == 0) + { + arm_has_v7 = TRUE; + arm_has_v6 = TRUE; + } + else if (strncmp (plat, "v6l", 3) == 0) + { + arm_has_v6 = TRUE; + } + } + } + close (fd); + } + + arm_tests_initialized = TRUE; +} + +#endif /* Linux elf */ + +#if defined(USE_ARM_SIMD) +pixman_bool_t +pixman_have_arm_simd (void) +{ + if (!arm_tests_initialized) + pixman_arm_read_auxv_or_cpu_features (); + + return arm_has_v6; +} + +#endif /* USE_ARM_SIMD */ + +#if defined(USE_ARM_NEON) +pixman_bool_t +pixman_have_arm_neon (void) +{ + if (!arm_tests_initialized) + pixman_arm_read_auxv_or_cpu_features (); + + return arm_has_neon; +} + +#endif /* USE_ARM_NEON */ + +#if defined(USE_ARM_IWMMXT) +pixman_bool_t +pixman_have_arm_iwmmxt (void) +{ + if (!arm_tests_initialized) + pixman_arm_read_auxv_or_cpu_features (); + + return arm_has_iwmmxt; +} + +#endif /* USE_ARM_IWMMXT */ + +#else /* !_MSC_VER && !Linux elf && !Android */ + +#define pixman_have_arm_simd() FALSE +#define pixman_have_arm_neon() FALSE +#define pixman_have_arm_iwmmxt() FALSE + +#endif + +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ + +pixman_implementation_t * +_pixman_arm_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_ARM_SIMD + if (!_pixman_disabled ("arm-simd") && pixman_have_arm_simd ()) + imp = _pixman_implementation_create_arm_simd (imp); +#endif + +#ifdef USE_ARM_IWMMXT + if (!_pixman_disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ()) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_ARM_NEON + if (!_pixman_disabled ("arm-neon") && pixman_have_arm_neon ()) + imp = _pixman_implementation_create_arm_neon (imp); +#endif + + return imp; +} + diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c index 0bfc90f..319d71f 100644 --- a/pixman/pixman-cpu.c +++ b/pixman/pixman-cpu.c @@ -26,11 +26,6 @@ #include #include -#if defined(USE_ARM_SIMD) && defined(_MSC_VER) -/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ -#include -#endif - #if defined(__APPLE__) #include "TargetConditionals.h" #endif @@ -192,241 +187,6 @@ pixman_have_vmx (void) #endif /* __APPLE__ */ #endif /* USE_VMX */ -#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) - -#if defined(_MSC_VER) - -#if defined(USE_ARM_SIMD) -extern int pixman_msvc_try_arm_simd_op (); - -pixman_bool_t -pixman_have_arm_simd (void) -{ - static pixman_bool_t initialized = FALSE; - static pixman_bool_t have_arm_simd = FALSE; - - if (!initialized) - { - __try { - pixman_msvc_try_arm_simd_op (); - have_arm_simd = TRUE; - } __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { - have_arm_simd = FALSE; - } - initialized = TRUE; - } - - return have_arm_simd; -} - -#endif /* USE_ARM_SIMD */ - -#if defined(USE_ARM_NEON) -extern int pixman_msvc_try_arm_neon_op (); - -pixman_bool_t -pixman_have_arm_neon (void) -{ - static pixman_bool_t initialized = FALSE; - static pixman_bool_t have_arm_neon = FALSE; - - if (!initialized) - { - __try - { - pixman_msvc_try_arm_neon_op (); - have_arm_neon = TRUE; - } - __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) - { - have_arm_neon = FALSE; - } - initialized = TRUE; - } - - return have_arm_neon; -} - -#endif /* USE_ARM_NEON */ - -#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */ - -/* Detection of ARM NEON on iOS is fairly simple because iOS binaries - * contain separate executable images for each processor architecture. - * So all we have to do is detect the armv7 architecture build. The - * operating system automatically runs the armv7 binary for armv7 devices - * and the armv6 binary for armv6 devices. - */ - -pixman_bool_t -pixman_have_arm_simd (void) -{ -#if defined(USE_ARM_SIMD) - return TRUE; -#else - return FALSE; -#endif -} - -pixman_bool_t -pixman_have_arm_neon (void) -{ -#if defined(USE_ARM_NEON) && defined(__ARM_NEON__) - /* This is an armv7 cpu build */ - return TRUE; -#else - /* This is an armv6 cpu build */ - return FALSE; -#endif -} - -pixman_bool_t -pixman_have_arm_iwmmxt (void) -{ -#if defined(USE_ARM_IWMMXT) - return FALSE; -#else - return FALSE; -#endif -} - -#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */ - -static pixman_bool_t arm_has_v7 = FALSE; -static pixman_bool_t arm_has_v6 = FALSE; -static pixman_bool_t arm_has_vfp = FALSE; -static pixman_bool_t arm_has_neon = FALSE; -static pixman_bool_t arm_has_iwmmxt = FALSE; -static pixman_bool_t arm_tests_initialized = FALSE; - -#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */ - -#include - -static void -pixman_arm_read_auxv_or_cpu_features () -{ - AndroidCpuFamily cpu_family; - uint64_t cpu_features; - - cpu_family = android_getCpuFamily(); - cpu_features = android_getCpuFeatures(); - - if (cpu_family == ANDROID_CPU_FAMILY_ARM) - { - if (cpu_features & ANDROID_CPU_ARM_FEATURE_ARMv7) - arm_has_v7 = TRUE; - - if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3) - arm_has_vfp = TRUE; - - if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) - arm_has_neon = TRUE; - } - - arm_tests_initialized = TRUE; -} - -#elif defined (__linux__) /* linux ELF */ - -#include -#include -#include -#include -#include -#include -#include - -static void -pixman_arm_read_auxv_or_cpu_features () -{ - int fd; - Elf32_auxv_t aux; - - fd = open ("/proc/self/auxv", O_RDONLY); - if (fd >= 0) - { - while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) - { - if (aux.a_type == AT_HWCAP) - { - uint32_t hwcap = aux.a_un.a_val; - /* hardcode these values to avoid depending on specific - * versions of the hwcap header, e.g. HWCAP_NEON - */ - arm_has_vfp = (hwcap & 64) != 0; - arm_has_iwmmxt = (hwcap & 512) != 0; - /* this flag is only present on kernel 2.6.29 */ - arm_has_neon = (hwcap & 4096) != 0; - } - else if (aux.a_type == AT_PLATFORM) - { - const char *plat = (const char*) aux.a_un.a_val; - if (strncmp (plat, "v7l", 3) == 0) - { - arm_has_v7 = TRUE; - arm_has_v6 = TRUE; - } - else if (strncmp (plat, "v6l", 3) == 0) - { - arm_has_v6 = TRUE; - } - } - } - close (fd); - } - - arm_tests_initialized = TRUE; -} - -#endif /* Linux elf */ - -#if defined(USE_ARM_SIMD) -pixman_bool_t -pixman_have_arm_simd (void) -{ - if (!arm_tests_initialized) - pixman_arm_read_auxv_or_cpu_features (); - - return arm_has_v6; -} - -#endif /* USE_ARM_SIMD */ - -#if defined(USE_ARM_NEON) -pixman_bool_t -pixman_have_arm_neon (void) -{ - if (!arm_tests_initialized) - pixman_arm_read_auxv_or_cpu_features (); - - return arm_has_neon; -} - -#endif /* USE_ARM_NEON */ - -#if defined(USE_ARM_IWMMXT) -pixman_bool_t -pixman_have_arm_iwmmxt (void) -{ - if (!arm_tests_initialized) - pixman_arm_read_auxv_or_cpu_features (); - - return arm_has_iwmmxt; -} - -#endif /* USE_ARM_IWMMXT */ - -#else /* !_MSC_VER && !Linux elf && !Android */ - -#define pixman_have_arm_simd() FALSE -#define pixman_have_arm_neon() FALSE -#define pixman_have_arm_iwmmxt() FALSE - -#endif - -#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ - #if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI) #if defined (__linux__) /* linux ELF */ @@ -533,24 +293,12 @@ _pixman_choose_implementation (void) imp = _pixman_implementation_create_fast_path (imp); imp = _pixman_x86_get_implementations (imp); + imp = _pixman_arm_get_implementations (imp); -#ifdef USE_ARM_SIMD - if (!_pixman_disabled ("arm-simd") && pixman_have_arm_simd ()) - imp = _pixman_implementation_create_arm_simd (imp); -#endif - -#ifdef USE_ARM_IWMMXT - if (!_pixman_disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ()) - imp = _pixman_implementation_create_mmx (imp); -#endif #ifdef USE_LOONGSON_MMI if (!_pixman_disabled ("loongson-mmi") && pixman_have_loongson_mmi ()) imp = _pixman_implementation_create_mmx (imp); #endif -#ifdef USE_ARM_NEON - if (!_pixman_disabled ("arm-neon") && pixman_have_arm_neon ()) - imp = _pixman_implementation_create_arm_neon (imp); -#endif #ifdef USE_MIPS_DSPR2 if (!_pixman_disabled ("mips-dspr2") && pixman_have_mips_dspr2 ()) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 67536c0..0a1c69f 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -592,6 +592,9 @@ pixman_implementation_t * _pixman_x86_get_implementations (pixman_implementation_t *imp); pixman_implementation_t * +_pixman_arm_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * _pixman_choose_implementation (void); pixman_bool_t -- 2.7.4