The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. // (This file gets included by juce_win32_NativeCode.cpp, rather than being
  19. // compiled on its own).
  20. #if JUCE_INCLUDED_FILE
  21. extern void juce_updateMultiMonitorInfo() throw();
  22. extern void juce_initialiseThreadEvents() throw();
  23. //==============================================================================
  24. void Logger::outputDebugString (const String& text) throw()
  25. {
  26. OutputDebugString (text + T("\n"));
  27. }
  28. void Logger::outputDebugPrintf (const tchar* format, ...) throw()
  29. {
  30. String text;
  31. va_list args;
  32. va_start (args, format);
  33. text.vprintf(format, args);
  34. outputDebugString (text);
  35. }
  36. //==============================================================================
  37. static int64 hiResTicksPerSecond;
  38. static double hiResTicksScaleFactor;
  39. //==============================================================================
  40. #if JUCE_USE_INTRINSICS
  41. // CPU info functions using intrinsics...
  42. #pragma intrinsic (__cpuid)
  43. #pragma intrinsic (__rdtsc)
  44. /*static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) throw()
  45. {
  46. int info [4];
  47. __cpuid (info, 1);
  48. if (familyModel != 0)
  49. *familyModel = info [0];
  50. if (extFeatures != 0)
  51. *extFeatures = info[1];
  52. return info[3];
  53. }*/
  54. const String SystemStats::getCpuVendor() throw()
  55. {
  56. int info [4];
  57. __cpuid (info, 0);
  58. char v [12];
  59. memcpy (v, info + 1, 4);
  60. memcpy (v + 4, info + 3, 4);
  61. memcpy (v + 8, info + 2, 4);
  62. return String (v, 12);
  63. }
  64. #else
  65. //==============================================================================
  66. // CPU info functions using old fashioned inline asm...
  67. /*static juce_noinline unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0)
  68. {
  69. unsigned int cpu = 0;
  70. unsigned int ext = 0;
  71. unsigned int family = 0;
  72. #if JUCE_GCC
  73. unsigned int dummy = 0;
  74. #endif
  75. #ifndef __MINGW32__
  76. __try
  77. #endif
  78. {
  79. #if JUCE_GCC
  80. __asm__ ("cpuid" : "=a" (family), "=b" (ext), "=c" (dummy),"=d" (cpu) : "a" (1));
  81. #else
  82. __asm
  83. {
  84. mov eax, 1
  85. cpuid
  86. mov cpu, edx
  87. mov family, eax
  88. mov ext, ebx
  89. }
  90. #endif
  91. }
  92. #ifndef __MINGW32__
  93. __except (EXCEPTION_EXECUTE_HANDLER)
  94. {
  95. return 0;
  96. }
  97. #endif
  98. if (familyModel != 0)
  99. *familyModel = family;
  100. if (extFeatures != 0)
  101. *extFeatures = ext;
  102. return cpu;
  103. }*/
  104. static void juce_getCpuVendor (char* const v)
  105. {
  106. int vendor[4];
  107. zeromem (vendor, 16);
  108. #ifdef JUCE_64BIT
  109. #else
  110. #ifndef __MINGW32__
  111. __try
  112. #endif
  113. {
  114. #if JUCE_GCC
  115. unsigned int dummy = 0;
  116. __asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0));
  117. #else
  118. __asm
  119. {
  120. mov eax, 0
  121. cpuid
  122. mov [vendor], ebx
  123. mov [vendor + 4], edx
  124. mov [vendor + 8], ecx
  125. }
  126. #endif
  127. }
  128. #ifndef __MINGW32__
  129. __except (EXCEPTION_EXECUTE_HANDLER)
  130. {
  131. *v = 0;
  132. }
  133. #endif
  134. #endif
  135. memcpy (v, vendor, 16);
  136. }
  137. const String SystemStats::getCpuVendor() throw()
  138. {
  139. char v [16];
  140. juce_getCpuVendor (v);
  141. return String (v, 16);
  142. }
  143. #endif
  144. //==============================================================================
  145. struct CPUFlags
  146. {
  147. bool hasMMX : 1;
  148. bool hasSSE : 1;
  149. bool hasSSE2 : 1;
  150. bool has3DNow : 1;
  151. };
  152. static CPUFlags cpuFlags;
  153. bool SystemStats::hasMMX() throw()
  154. {
  155. return cpuFlags.hasMMX;
  156. }
  157. bool SystemStats::hasSSE() throw()
  158. {
  159. return cpuFlags.hasSSE;
  160. }
  161. bool SystemStats::hasSSE2() throw()
  162. {
  163. return cpuFlags.hasSSE2;
  164. }
  165. bool SystemStats::has3DNow() throw()
  166. {
  167. return cpuFlags.has3DNow;
  168. }
  169. void SystemStats::initialiseStats() throw()
  170. {
  171. juce_initialiseThreadEvents();
  172. cpuFlags.hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0;
  173. cpuFlags.hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
  174. cpuFlags.hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0;
  175. #ifdef PF_AMD3D_INSTRUCTIONS_AVAILABLE
  176. cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_AMD3D_INSTRUCTIONS_AVAILABLE) != 0;
  177. #else
  178. cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_3DNOW_INSTRUCTIONS_AVAILABLE) != 0;
  179. #endif
  180. LARGE_INTEGER f;
  181. QueryPerformanceFrequency (&f);
  182. hiResTicksPerSecond = f.QuadPart;
  183. hiResTicksScaleFactor = 1000.0 / hiResTicksPerSecond;
  184. String s (SystemStats::getJUCEVersion());
  185. #ifdef JUCE_DEBUG
  186. const MMRESULT res = timeBeginPeriod (1);
  187. jassert (res == TIMERR_NOERROR);
  188. #else
  189. timeBeginPeriod (1);
  190. #endif
  191. #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  192. _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  193. #endif
  194. }
  195. //==============================================================================
  196. SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() throw()
  197. {
  198. OSVERSIONINFO info;
  199. info.dwOSVersionInfoSize = sizeof (info);
  200. GetVersionEx (&info);
  201. if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
  202. {
  203. switch (info.dwMajorVersion)
  204. {
  205. case 5:
  206. return (info.dwMinorVersion == 0) ? Win2000 : WinXP;
  207. case 6:
  208. return WinVista;
  209. default:
  210. jassertfalse // !! not a supported OS!
  211. break;
  212. }
  213. }
  214. else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  215. {
  216. jassert (info.dwMinorVersion != 0); // !! still running on Windows 95??
  217. return Win98;
  218. }
  219. return UnknownOS;
  220. }
  221. const String SystemStats::getOperatingSystemName() throw()
  222. {
  223. const char* name = "Unknown OS";
  224. switch (getOperatingSystemType())
  225. {
  226. case WinVista:
  227. name = "Windows Vista";
  228. break;
  229. case WinXP:
  230. name = "Windows XP";
  231. break;
  232. case Win2000:
  233. name = "Windows 2000";
  234. break;
  235. case Win98:
  236. name = "Windows 98";
  237. break;
  238. default:
  239. jassertfalse // !! new type of OS?
  240. break;
  241. }
  242. return name;
  243. }
  244. bool SystemStats::isOperatingSystem64Bit() throw()
  245. {
  246. #ifdef _WIN64
  247. return true;
  248. #else
  249. typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  250. LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (L"kernel32"), "IsWow64Process");
  251. BOOL isWow64 = FALSE;
  252. return (fnIsWow64Process != 0)
  253. && fnIsWow64Process (GetCurrentProcess(), &isWow64)
  254. && (isWow64 != FALSE);
  255. #endif
  256. }
  257. //==============================================================================
  258. int SystemStats::getMemorySizeInMegabytes() throw()
  259. {
  260. MEMORYSTATUS mem;
  261. GlobalMemoryStatus (&mem);
  262. return (int) (mem.dwTotalPhys / (1024 * 1024)) + 1;
  263. }
  264. int SystemStats::getNumCpus() throw()
  265. {
  266. SYSTEM_INFO systemInfo;
  267. GetSystemInfo (&systemInfo);
  268. return systemInfo.dwNumberOfProcessors;
  269. }
  270. //==============================================================================
  271. uint32 juce_millisecondsSinceStartup() throw()
  272. {
  273. return (uint32) GetTickCount();
  274. }
  275. int64 Time::getHighResolutionTicks() throw()
  276. {
  277. LARGE_INTEGER ticks;
  278. QueryPerformanceCounter (&ticks);
  279. const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000;
  280. const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart;
  281. // fix for a very obscure PCI hardware bug that can make the counter
  282. // sometimes jump forwards by a few seconds..
  283. static int64 hiResTicksOffset = 0;
  284. const int64 offsetDrift = abs64 (newOffset - hiResTicksOffset);
  285. if (offsetDrift > (hiResTicksPerSecond >> 1))
  286. hiResTicksOffset = newOffset;
  287. return ticks.QuadPart + hiResTicksOffset;
  288. }
  289. double Time::getMillisecondCounterHiRes() throw()
  290. {
  291. return getHighResolutionTicks() * hiResTicksScaleFactor;
  292. }
  293. int64 Time::getHighResolutionTicksPerSecond() throw()
  294. {
  295. return hiResTicksPerSecond;
  296. }
  297. int64 SystemStats::getClockCycleCounter() throw()
  298. {
  299. #if JUCE_USE_INTRINSICS
  300. // MS intrinsics version...
  301. return __rdtsc();
  302. #elif JUCE_GCC
  303. // GNU inline asm version...
  304. unsigned int hi = 0, lo = 0;
  305. __asm__ __volatile__ (
  306. "xor %%eax, %%eax \n\
  307. xor %%edx, %%edx \n\
  308. rdtsc \n\
  309. movl %%eax, %[lo] \n\
  310. movl %%edx, %[hi]"
  311. :
  312. : [hi] "m" (hi),
  313. [lo] "m" (lo)
  314. : "cc", "eax", "ebx", "ecx", "edx", "memory");
  315. return (int64) ((((uint64) hi) << 32) | lo);
  316. #else
  317. // MSVC inline asm version...
  318. unsigned int hi = 0, lo = 0;
  319. __asm
  320. {
  321. xor eax, eax
  322. xor edx, edx
  323. rdtsc
  324. mov lo, eax
  325. mov hi, edx
  326. }
  327. return (int64) ((((uint64) hi) << 32) | lo);
  328. #endif
  329. }
  330. int SystemStats::getCpuSpeedInMegaherz() throw()
  331. {
  332. const int64 cycles = SystemStats::getClockCycleCounter();
  333. const uint32 millis = Time::getMillisecondCounter();
  334. int lastResult = 0;
  335. for (;;)
  336. {
  337. int n = 1000000;
  338. while (--n > 0) {}
  339. const uint32 millisElapsed = Time::getMillisecondCounter() - millis;
  340. const int64 cyclesNow = SystemStats::getClockCycleCounter();
  341. if (millisElapsed > 80)
  342. {
  343. const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000);
  344. if (millisElapsed > 500 || (lastResult == newResult && newResult > 100))
  345. return newResult;
  346. lastResult = newResult;
  347. }
  348. }
  349. }
  350. //==============================================================================
  351. bool Time::setSystemTimeToThisTime() const throw()
  352. {
  353. SYSTEMTIME st;
  354. st.wDayOfWeek = 0;
  355. st.wYear = (WORD) getYear();
  356. st.wMonth = (WORD) (getMonth() + 1);
  357. st.wDay = (WORD) getDayOfMonth();
  358. st.wHour = (WORD) getHours();
  359. st.wMinute = (WORD) getMinutes();
  360. st.wSecond = (WORD) getSeconds();
  361. st.wMilliseconds = (WORD) (millisSinceEpoch % 1000);
  362. // do this twice because of daylight saving conversion problems - the
  363. // first one sets it up, the second one kicks it in.
  364. return SetLocalTime (&st) != 0
  365. && SetLocalTime (&st) != 0;
  366. }
  367. int SystemStats::getPageSize() throw()
  368. {
  369. SYSTEM_INFO systemInfo;
  370. GetSystemInfo (&systemInfo);
  371. return systemInfo.dwPageSize;
  372. }
  373. #endif