| @@ -140,6 +140,7 @@ static String getAllSystemInfo() | |||||
| << "CPU has 3DNOW: " << (SystemStats::has3DNow() ? "yes" : "no") << newLine | << "CPU has 3DNOW: " << (SystemStats::has3DNow() ? "yes" : "no") << newLine | ||||
| << "CPU has AVX: " << (SystemStats::hasAVX() ? "yes" : "no") << newLine | << "CPU has AVX: " << (SystemStats::hasAVX() ? "yes" : "no") << newLine | ||||
| << "CPU has AVX2: " << (SystemStats::hasAVX2() ? "yes" : "no") << newLine | << "CPU has AVX2: " << (SystemStats::hasAVX2() ? "yes" : "no") << newLine | ||||
| << "CPU has Neon: " << (SystemStats::hasNeon() ? "yes" : "no") << newLine | |||||
| << newLine; | << newLine; | ||||
| systemInfo | systemInfo | ||||
| @@ -349,13 +349,23 @@ private: | |||||
| if (! isLibrary()) | if (! isLibrary()) | ||||
| mo << "SET(BINARY_NAME \"juce_jni\")" << newLine << newLine; | mo << "SET(BINARY_NAME \"juce_jni\")" << newLine << newLine; | ||||
| mo << "add_library(\"cpufeatures\" STATIC \"${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c\")" << newLine << newLine; | |||||
| { | { | ||||
| StringArray projectDefines (getEscapedPreprocessorDefs (getProjectPreprocessorDefs())); | StringArray projectDefines (getEscapedPreprocessorDefs (getProjectPreprocessorDefs())); | ||||
| if (projectDefines.size() > 0) | if (projectDefines.size() > 0) | ||||
| mo << "add_definitions(" << projectDefines.joinIntoString (" ") << ")" << newLine << newLine; | mo << "add_definitions(" << projectDefines.joinIntoString (" ") << ")" << newLine << newLine; | ||||
| } | } | ||||
| writeCmakePathLines (mo, "", "include_directories( AFTER", extraSearchPaths); | |||||
| { | |||||
| mo << "include_directories( AFTER" << newLine; | |||||
| for (auto& path : extraSearchPaths) | |||||
| mo << " \"" << escapeDirectoryForCmake (path) << "\"" << newLine; | |||||
| mo << " \"${ANDROID_NDK}/sources/android/cpufeatures\"" << newLine; | |||||
| mo << ")" << newLine << newLine; | |||||
| } | |||||
| const String& cfgExtraLinkerFlags = getExtraLinkerFlagsString(); | const String& cfgExtraLinkerFlags = getExtraLinkerFlagsString(); | ||||
| if (cfgExtraLinkerFlags.isNotEmpty()) | if (cfgExtraLinkerFlags.isNotEmpty()) | ||||
| @@ -460,6 +470,8 @@ private: | |||||
| for (auto& lib : libraries) | for (auto& lib : libraries) | ||||
| mo << " ${" << lib.toLowerCase().replaceCharacter (L' ', L'_') << "}" << newLine; | mo << " ${" << lib.toLowerCase().replaceCharacter (L' ', L'_') << "}" << newLine; | ||||
| mo << " \"cpufeatures\"" << newLine; | |||||
| } | } | ||||
| mo << ")" << newLine; | mo << ")" << newLine; | ||||
| @@ -253,6 +253,10 @@ | |||||
| #include <fnmatch.h> | #include <fnmatch.h> | ||||
| #include <sys/wait.h> | #include <sys/wait.h> | ||||
| #include <android/api-level.h> | #include <android/api-level.h> | ||||
| // If you are getting include errors here, then you to re-build the Projucer | |||||
| // and re-save your .jucer file. | |||||
| #include <cpu-features.h> | |||||
| #endif | #endif | ||||
| // Need to clear various moronic redefinitions made by system headers.. | // Need to clear various moronic redefinitions made by system headers.. | ||||
| @@ -343,7 +343,36 @@ String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getU | |||||
| //============================================================================== | //============================================================================== | ||||
| void CPUInformation::initialise() noexcept | void CPUInformation::initialise() noexcept | ||||
| { | { | ||||
| numPhysicalCPUs = numLogicalCPUs = jmax ((int) 1, (int) sysconf (_SC_NPROCESSORS_ONLN)); | |||||
| numPhysicalCPUs = numLogicalCPUs = jmax ((int) 1, (int) android_getCpuCount()); | |||||
| auto cpuFamily = android_getCpuFamily(); | |||||
| auto cpuFeatures = android_getCpuFeatures(); | |||||
| if (cpuFamily == ANDROID_CPU_FAMILY_X86 || cpuFamily == ANDROID_CPU_FAMILY_X86_64) | |||||
| { | |||||
| hasMMX = hasSSE = hasSSE2 = (cpuFamily == ANDROID_CPU_FAMILY_X86_64); | |||||
| hasSSSE3 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_SSSE3) != 0); | |||||
| hasSSE41 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_SSE4_1) != 0); | |||||
| hasSSE42 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_SSE4_2) != 0); | |||||
| hasAVX = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_AVX) != 0); | |||||
| hasAVX2 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_AVX2) != 0); | |||||
| // Google does not distinguish between MMX, SSE, SSE2, SSE3 and SSSE3. So | |||||
| // I assume (and quick Google searches seem to confirm this) that there are | |||||
| // only devices out there that either support all of this or none of this. | |||||
| if (hasSSSE3) | |||||
| hasMMX = hasSSE = hasSSE2 = hasSSE3 = true; | |||||
| } | |||||
| else if (cpuFamily == ANDROID_CPU_FAMILY_ARM) | |||||
| { | |||||
| hasNeon = ((cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON) != 0); | |||||
| } | |||||
| else if (cpuFamily == ANDROID_CPU_FAMILY_ARM64) | |||||
| { | |||||
| // all arm 64-bit cpus have neon | |||||
| hasNeon = true; | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -91,7 +91,7 @@ struct CPUInformation | |||||
| bool hasMMX = false, hasSSE = false, hasSSE2 = false, hasSSE3 = false, | bool hasMMX = false, hasSSE = false, hasSSE2 = false, hasSSE3 = false, | ||||
| has3DNow = false, hasSSSE3 = false, hasSSE41 = false, | has3DNow = false, hasSSSE3 = false, hasSSE41 = false, | ||||
| hasSSE42 = false, hasAVX = false, hasAVX2 = false; | |||||
| hasSSE42 = false, hasAVX = false, hasAVX2 = false, hasNeon = false; | |||||
| }; | }; | ||||
| static const CPUInformation& getCPUInformation() noexcept | static const CPUInformation& getCPUInformation() noexcept | ||||
| @@ -112,6 +112,7 @@ bool SystemStats::hasSSE41() noexcept { return getCPUInformation().has | |||||
| bool SystemStats::hasSSE42() noexcept { return getCPUInformation().hasSSE42; } | bool SystemStats::hasSSE42() noexcept { return getCPUInformation().hasSSE42; } | ||||
| bool SystemStats::hasAVX() noexcept { return getCPUInformation().hasAVX; } | bool SystemStats::hasAVX() noexcept { return getCPUInformation().hasAVX; } | ||||
| bool SystemStats::hasAVX2() noexcept { return getCPUInformation().hasAVX2; } | bool SystemStats::hasAVX2() noexcept { return getCPUInformation().hasAVX2; } | ||||
| bool SystemStats::hasNeon() noexcept { return getCPUInformation().hasNeon; } | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -171,6 +171,7 @@ public: | |||||
| static bool hasSSE42() noexcept; /**< Returns true if Intel SSE4.2 instructions are available. */ | static bool hasSSE42() noexcept; /**< Returns true if Intel SSE4.2 instructions are available. */ | ||||
| static bool hasAVX() noexcept; /**< Returns true if Intel AVX instructions are available. */ | static bool hasAVX() noexcept; /**< Returns true if Intel AVX instructions are available. */ | ||||
| static bool hasAVX2() noexcept; /**< Returns true if Intel AVX2 instructions are available. */ | static bool hasAVX2() noexcept; /**< Returns true if Intel AVX2 instructions are available. */ | ||||
| static bool hasNeon() noexcept; /**< Returns true if ARM NEON instructions are available. */ | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Finds out how much RAM is in the machine. | /** Finds out how much RAM is in the machine. | ||||