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.

394 lines
11KB

  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_initialiseThreadEvents();
  22. //==============================================================================
  23. void Logger::outputDebugString (const String& text) throw()
  24. {
  25. OutputDebugString (text + T("\n"));
  26. }
  27. void Logger::outputDebugPrintf (const tchar* format, ...) throw()
  28. {
  29. String text;
  30. va_list args;
  31. va_start (args, format);
  32. text.vprintf(format, args);
  33. outputDebugString (text);
  34. }
  35. //==============================================================================
  36. static int64 hiResTicksPerSecond;
  37. static double hiResTicksScaleFactor;
  38. //==============================================================================
  39. #if JUCE_USE_INTRINSICS
  40. // CPU info functions using intrinsics...
  41. #pragma intrinsic (__cpuid)
  42. #pragma intrinsic (__rdtsc)
  43. const String SystemStats::getCpuVendor() throw()
  44. {
  45. int info [4];
  46. __cpuid (info, 0);
  47. char v [12];
  48. memcpy (v, info + 1, 4);
  49. memcpy (v + 4, info + 3, 4);
  50. memcpy (v + 8, info + 2, 4);
  51. return String (v, 12);
  52. }
  53. #else
  54. //==============================================================================
  55. // CPU info functions using old fashioned inline asm...
  56. static void juce_getCpuVendor (char* const v)
  57. {
  58. int vendor[4];
  59. zeromem (vendor, 16);
  60. #ifdef JUCE_64BIT
  61. #else
  62. #ifndef __MINGW32__
  63. __try
  64. #endif
  65. {
  66. #if JUCE_GCC
  67. unsigned int dummy = 0;
  68. __asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0));
  69. #else
  70. __asm
  71. {
  72. mov eax, 0
  73. cpuid
  74. mov [vendor], ebx
  75. mov [vendor + 4], edx
  76. mov [vendor + 8], ecx
  77. }
  78. #endif
  79. }
  80. #ifndef __MINGW32__
  81. __except (EXCEPTION_EXECUTE_HANDLER)
  82. {
  83. *v = 0;
  84. }
  85. #endif
  86. #endif
  87. memcpy (v, vendor, 16);
  88. }
  89. const String SystemStats::getCpuVendor() throw()
  90. {
  91. char v [16];
  92. juce_getCpuVendor (v);
  93. return String (v, 16);
  94. }
  95. #endif
  96. //==============================================================================
  97. struct CPUFlags
  98. {
  99. bool hasMMX : 1;
  100. bool hasSSE : 1;
  101. bool hasSSE2 : 1;
  102. bool has3DNow : 1;
  103. };
  104. static CPUFlags cpuFlags;
  105. bool SystemStats::hasMMX() throw()
  106. {
  107. return cpuFlags.hasMMX;
  108. }
  109. bool SystemStats::hasSSE() throw()
  110. {
  111. return cpuFlags.hasSSE;
  112. }
  113. bool SystemStats::hasSSE2() throw()
  114. {
  115. return cpuFlags.hasSSE2;
  116. }
  117. bool SystemStats::has3DNow() throw()
  118. {
  119. return cpuFlags.has3DNow;
  120. }
  121. void SystemStats::initialiseStats() throw()
  122. {
  123. juce_initialiseThreadEvents();
  124. cpuFlags.hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0;
  125. cpuFlags.hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
  126. cpuFlags.hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0;
  127. #ifdef PF_AMD3D_INSTRUCTIONS_AVAILABLE
  128. cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_AMD3D_INSTRUCTIONS_AVAILABLE) != 0;
  129. #else
  130. cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_3DNOW_INSTRUCTIONS_AVAILABLE) != 0;
  131. #endif
  132. LARGE_INTEGER f;
  133. QueryPerformanceFrequency (&f);
  134. hiResTicksPerSecond = f.QuadPart;
  135. hiResTicksScaleFactor = 1000.0 / hiResTicksPerSecond;
  136. String s (SystemStats::getJUCEVersion());
  137. #ifdef JUCE_DEBUG
  138. const MMRESULT res = timeBeginPeriod (1);
  139. jassert (res == TIMERR_NOERROR);
  140. #else
  141. timeBeginPeriod (1);
  142. #endif
  143. #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  144. _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  145. #endif
  146. }
  147. //==============================================================================
  148. SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() throw()
  149. {
  150. OSVERSIONINFO info;
  151. info.dwOSVersionInfoSize = sizeof (info);
  152. GetVersionEx (&info);
  153. if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
  154. {
  155. switch (info.dwMajorVersion)
  156. {
  157. case 5: return (info.dwMinorVersion == 0) ? Win2000 : WinXP;
  158. case 6: return (info.dwMinorVersion == 0) ? WinVista : Windows7;
  159. default: jassertfalse; break; // !! not a supported OS!
  160. }
  161. }
  162. else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  163. {
  164. jassert (info.dwMinorVersion != 0); // !! still running on Windows 95??
  165. return Win98;
  166. }
  167. return UnknownOS;
  168. }
  169. const String SystemStats::getOperatingSystemName() throw()
  170. {
  171. const char* name = "Unknown OS";
  172. switch (getOperatingSystemType())
  173. {
  174. case Windows7: name = "Windows 7"; break;
  175. case WinVista: name = "Windows Vista"; break;
  176. case WinXP: name = "Windows XP"; break;
  177. case Win2000: name = "Windows 2000"; break;
  178. case Win98: name = "Windows 98"; break;
  179. default: jassertfalse; break; // !! new type of OS?
  180. }
  181. return name;
  182. }
  183. bool SystemStats::isOperatingSystem64Bit() throw()
  184. {
  185. #ifdef _WIN64
  186. return true;
  187. #else
  188. typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  189. LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (L"kernel32"), "IsWow64Process");
  190. BOOL isWow64 = FALSE;
  191. return (fnIsWow64Process != 0)
  192. && fnIsWow64Process (GetCurrentProcess(), &isWow64)
  193. && (isWow64 != FALSE);
  194. #endif
  195. }
  196. //==============================================================================
  197. int SystemStats::getMemorySizeInMegabytes() throw()
  198. {
  199. MEMORYSTATUSEX mem;
  200. mem.dwLength = sizeof (mem);
  201. GlobalMemoryStatusEx (&mem);
  202. return (int) (mem.ullTotalPhys / (1024 * 1024)) + 1;
  203. }
  204. int SystemStats::getNumCpus() throw()
  205. {
  206. SYSTEM_INFO systemInfo;
  207. GetSystemInfo (&systemInfo);
  208. return systemInfo.dwNumberOfProcessors;
  209. }
  210. //==============================================================================
  211. uint32 juce_millisecondsSinceStartup() throw()
  212. {
  213. return (uint32) GetTickCount();
  214. }
  215. int64 Time::getHighResolutionTicks() throw()
  216. {
  217. LARGE_INTEGER ticks;
  218. QueryPerformanceCounter (&ticks);
  219. const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000;
  220. const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart;
  221. // fix for a very obscure PCI hardware bug that can make the counter
  222. // sometimes jump forwards by a few seconds..
  223. static int64 hiResTicksOffset = 0;
  224. const int64 offsetDrift = abs64 (newOffset - hiResTicksOffset);
  225. if (offsetDrift > (hiResTicksPerSecond >> 1))
  226. hiResTicksOffset = newOffset;
  227. return ticks.QuadPart + hiResTicksOffset;
  228. }
  229. double Time::getMillisecondCounterHiRes() throw()
  230. {
  231. return getHighResolutionTicks() * hiResTicksScaleFactor;
  232. }
  233. int64 Time::getHighResolutionTicksPerSecond() throw()
  234. {
  235. return hiResTicksPerSecond;
  236. }
  237. int64 SystemStats::getClockCycleCounter() throw()
  238. {
  239. #if JUCE_USE_INTRINSICS
  240. // MS intrinsics version...
  241. return __rdtsc();
  242. #elif JUCE_GCC
  243. // GNU inline asm version...
  244. unsigned int hi = 0, lo = 0;
  245. __asm__ __volatile__ (
  246. "xor %%eax, %%eax \n\
  247. xor %%edx, %%edx \n\
  248. rdtsc \n\
  249. movl %%eax, %[lo] \n\
  250. movl %%edx, %[hi]"
  251. :
  252. : [hi] "m" (hi),
  253. [lo] "m" (lo)
  254. : "cc", "eax", "ebx", "ecx", "edx", "memory");
  255. return (int64) ((((uint64) hi) << 32) | lo);
  256. #else
  257. // MSVC inline asm version...
  258. unsigned int hi = 0, lo = 0;
  259. __asm
  260. {
  261. xor eax, eax
  262. xor edx, edx
  263. rdtsc
  264. mov lo, eax
  265. mov hi, edx
  266. }
  267. return (int64) ((((uint64) hi) << 32) | lo);
  268. #endif
  269. }
  270. int SystemStats::getCpuSpeedInMegaherz() throw()
  271. {
  272. const int64 cycles = SystemStats::getClockCycleCounter();
  273. const uint32 millis = Time::getMillisecondCounter();
  274. int lastResult = 0;
  275. for (;;)
  276. {
  277. int n = 1000000;
  278. while (--n > 0) {}
  279. const uint32 millisElapsed = Time::getMillisecondCounter() - millis;
  280. const int64 cyclesNow = SystemStats::getClockCycleCounter();
  281. if (millisElapsed > 80)
  282. {
  283. const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000);
  284. if (millisElapsed > 500 || (lastResult == newResult && newResult > 100))
  285. return newResult;
  286. lastResult = newResult;
  287. }
  288. }
  289. }
  290. //==============================================================================
  291. bool Time::setSystemTimeToThisTime() const throw()
  292. {
  293. SYSTEMTIME st;
  294. st.wDayOfWeek = 0;
  295. st.wYear = (WORD) getYear();
  296. st.wMonth = (WORD) (getMonth() + 1);
  297. st.wDay = (WORD) getDayOfMonth();
  298. st.wHour = (WORD) getHours();
  299. st.wMinute = (WORD) getMinutes();
  300. st.wSecond = (WORD) getSeconds();
  301. st.wMilliseconds = (WORD) (millisSinceEpoch % 1000);
  302. // do this twice because of daylight saving conversion problems - the
  303. // first one sets it up, the second one kicks it in.
  304. return SetLocalTime (&st) != 0
  305. && SetLocalTime (&st) != 0;
  306. }
  307. int SystemStats::getPageSize() throw()
  308. {
  309. SYSTEM_INFO systemInfo;
  310. GetSystemInfo (&systemInfo);
  311. return systemInfo.dwPageSize;
  312. }
  313. #endif