]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/os.cpp
CIrrDeviceWin32: drop all video mode code
[irrlicht.git] / source / Irrlicht / os.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "os.h"\r
6 #include "irrString.h"\r
7 #include "IrrCompileConfig.h"\r
8 #include "irrMath.h"\r
9 \r
10 #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)\r
11         #include <SDL/SDL_endian.h>\r
12         #define bswap_16(X) SDL_Swap16(X)\r
13         #define bswap_32(X) SDL_Swap32(X)\r
14         #define bswap_64(X) SDL_Swap64(X)\r
15 #elif defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER > 1298)\r
16         #include <stdlib.h>\r
17         #define bswap_16(X) _byteswap_ushort(X)\r
18         #define bswap_32(X) _byteswap_ulong(X)\r
19         #define bswap_64(X) _byteswap_uint64(X)\r
20 #if (_MSC_VER >= 1400)\r
21         #define localtime _localtime_s\r
22 #endif\r
23 #elif defined(_IRR_OSX_PLATFORM_) || defined(_IRR_IOS_PLATFORM_)\r
24         #include <libkern/OSByteOrder.h>\r
25         #define bswap_16(X) OSReadSwapInt16(&X,0)\r
26         #define bswap_32(X) OSReadSwapInt32(&X,0)\r
27         #define bswap_64(X) OSReadSwapInt64(&X,0)\r
28 #elif defined(__FreeBSD__) || defined(__OpenBSD__)\r
29         #include <sys/endian.h>\r
30         #define bswap_16(X) bswap16(X)\r
31         #define bswap_32(X) bswap32(X)\r
32         #define bswap_64(X) bswap64(X)\r
33 #elif !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__PPC__) && !defined(_IRR_WINDOWS_API_)\r
34         #include <byteswap.h>\r
35 #else\r
36         #define bswap_16(X) ((((X)&0xFF) << 8) | (((X)&0xFF00) >> 8))\r
37         #define bswap_32(X) ((((X)&0x000000FF) << 24) | (((X)&0xFF000000) >> 24) | (((X)&0x0000FF00) << 8) | (((X) &0x00FF0000) >> 8))\r
38         #define bswap_64(X) ((((X)&0x00000000000000FF) << 56) | (((X)&0xFF00000000000000) >> 56) | (((X)&0x000000000000FF00) << 40) | (((X)&0x00FF000000000000) >> 40) | (((X)&0x0000000000FF0000) << 24) | (((X)&0x0000FF0000000000) >> 24) | (((X)&0x00000000FF000000) << 8) | (((X) &0x000000FF00000000) >> 8))\r
39 #endif\r
40 \r
41 namespace irr\r
42 {\r
43 namespace os\r
44 {\r
45         u16 Byteswap::byteswap(u16 num) {return bswap_16(num);}\r
46         s16 Byteswap::byteswap(s16 num) {return bswap_16(num);}\r
47         u32 Byteswap::byteswap(u32 num) {return bswap_32(num);}\r
48         s32 Byteswap::byteswap(s32 num) {return bswap_32(num);}\r
49         u64 Byteswap::byteswap(u64 num) {return bswap_64(num);}\r
50         s64 Byteswap::byteswap(s64 num) {return bswap_64(num);}\r
51         f32 Byteswap::byteswap(f32 num) {u32 tmp=IR(num); tmp=bswap_32(tmp); return (FR(tmp));}\r
52         // prevent accidental byte swapping of chars\r
53         u8  Byteswap::byteswap(u8 num)  {return num;}\r
54         c8  Byteswap::byteswap(c8 num)  {return num;}\r
55 }\r
56 }\r
57 \r
58 #if defined(_IRR_WINDOWS_API_)\r
59 // ----------------------------------------------------------------\r
60 // Windows specific functions\r
61 // ----------------------------------------------------------------\r
62 \r
63 #ifdef _IRR_XBOX_PLATFORM_\r
64 #include <xtl.h>\r
65 #else\r
66 #define WIN32_LEAN_AND_MEAN\r
67 #include <windows.h>\r
68 #include <time.h>\r
69 #endif\r
70 \r
71 namespace irr\r
72 {\r
73 namespace os\r
74 {\r
75         //! prints a debuginfo string\r
76         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
77         {\r
78 #if defined (_WIN32_WCE )\r
79                 core::stringw tmp(message);\r
80                 tmp += L"\n";\r
81                 OutputDebugStringW(tmp.c_str());\r
82 #else\r
83                 core::stringc tmp(message);\r
84                 tmp += "\n";\r
85                 OutputDebugStringA(tmp.c_str());\r
86                 printf("%s", tmp.c_str());\r
87 #endif\r
88         }\r
89 \r
90         static LARGE_INTEGER HighPerformanceFreq;\r
91         static BOOL HighPerformanceTimerSupport = FALSE;\r
92         static BOOL MultiCore = FALSE;\r
93 \r
94         void Timer::initTimer(bool usePerformanceTimer)\r
95         {\r
96 #if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_)\r
97                 // workaround for hires timer on multiple core systems, bios bugs result in bad hires timers.\r
98                 SYSTEM_INFO sysinfo;\r
99                 GetSystemInfo(&sysinfo);\r
100                 MultiCore = (sysinfo.dwNumberOfProcessors > 1);\r
101 #endif\r
102                 if (usePerformanceTimer)\r
103                         HighPerformanceTimerSupport = QueryPerformanceFrequency(&HighPerformanceFreq);\r
104                 else\r
105                         HighPerformanceTimerSupport = FALSE;\r
106                 initVirtualTimer();\r
107         }\r
108 \r
109         u32 Timer::getRealTime()\r
110         {\r
111                 if (HighPerformanceTimerSupport)\r
112                 {\r
113 #if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_)\r
114                         // Avoid potential timing inaccuracies across multiple cores by\r
115                         // temporarily setting the affinity of this process to one core.\r
116                         DWORD_PTR affinityMask=0;\r
117                         if(MultiCore)\r
118                                 affinityMask = SetThreadAffinityMask(GetCurrentThread(), 1);\r
119 #endif\r
120                         LARGE_INTEGER nTime;\r
121                         BOOL queriedOK = QueryPerformanceCounter(&nTime);\r
122 \r
123 #if !defined(_WIN32_WCE)  && !defined (_IRR_XBOX_PLATFORM_)\r
124                         // Restore the true affinity.\r
125                         if(MultiCore)\r
126                                 (void)SetThreadAffinityMask(GetCurrentThread(), affinityMask);\r
127 #endif\r
128                         if(queriedOK)\r
129                                 return u32((nTime.QuadPart) * 1000 / HighPerformanceFreq.QuadPart);\r
130 \r
131                 }\r
132 \r
133                 return GetTickCount();\r
134         }\r
135 \r
136 } // end namespace os\r
137 \r
138 \r
139 #elif defined( _IRR_ANDROID_PLATFORM_ )\r
140 \r
141 // ----------------------------------------------------------------\r
142 // Android version\r
143 // ----------------------------------------------------------------\r
144 \r
145 #include <android/log.h>\r
146 \r
147 namespace irr\r
148 {\r
149 namespace os\r
150 {\r
151 \r
152         //! prints a debuginfo string\r
153         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
154         {\r
155                 android_LogPriority LogLevel = ANDROID_LOG_UNKNOWN;\r
156 \r
157                 switch (ll)\r
158                 {\r
159                 case ELL_DEBUG:\r
160                         LogLevel = ANDROID_LOG_DEBUG;\r
161                         break;\r
162                 case ELL_INFORMATION:\r
163                         LogLevel = ANDROID_LOG_INFO;\r
164                         break;\r
165                 case ELL_WARNING:\r
166                         LogLevel = ANDROID_LOG_WARN;\r
167                         break;\r
168                 case ELL_ERROR:\r
169                         LogLevel = ANDROID_LOG_ERROR;\r
170                         break;\r
171                 default: // ELL_NONE\r
172                         LogLevel = ANDROID_LOG_VERBOSE;\r
173                         break;\r
174                 }\r
175 \r
176                 // Android logcat restricts log-output and cuts the rest of the message away. But we want it all.\r
177                 // On my device max-len is 1023 (+ 0 byte). Some websites claim a limit of 4096 so maybe different numbers on different devices.\r
178                 const size_t maxLogLen = 1023;\r
179                 size_t msgLen = strlen(message);\r
180                 size_t start = 0;\r
181                 while ( msgLen-start > maxLogLen )\r
182                 {\r
183                         __android_log_print(LogLevel, "Irrlicht", "%.*s\n", maxLogLen, &message[start]);\r
184                         start += maxLogLen;\r
185                 }\r
186                 __android_log_print(LogLevel, "Irrlicht", "%s\n", &message[start]);\r
187         }\r
188 \r
189         void Timer::initTimer(bool usePerformanceTimer)\r
190         {\r
191                 initVirtualTimer();\r
192         }\r
193 \r
194         u32 Timer::getRealTime()\r
195         {\r
196                 timeval tv;\r
197                 gettimeofday(&tv, 0);\r
198                 return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000);\r
199         }\r
200 } // end namespace os\r
201 \r
202 #elif defined(_IRR_EMSCRIPTEN_PLATFORM_)\r
203 \r
204 // ----------------------------------------------------------------\r
205 // emscripten version\r
206 // ----------------------------------------------------------------\r
207 \r
208 #include <emscripten.h>\r
209 #include <time.h>\r
210 #include <sys/time.h>\r
211 \r
212 namespace irr\r
213 {\r
214 namespace os\r
215 {\r
216 \r
217         //! prints a debuginfo string\r
218         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
219         {\r
220         int log_level;\r
221                 switch (ll)\r
222                 {\r
223                 case ELL_DEBUG:\r
224             log_level=0;\r
225                 break;\r
226                 case ELL_INFORMATION:\r
227            log_level=0;\r
228                 break;\r
229                 case ELL_WARNING:\r
230             log_level=EM_LOG_WARN;\r
231                         break;\r
232                 case ELL_ERROR:\r
233             log_level=EM_LOG_ERROR;\r
234                 break;\r
235                 default: // ELL_NONE\r
236             log_level=0;\r
237                         break;\r
238                 }\r
239         emscripten_log(log_level, "%s", message);       // Note: not adding \n as emscripten_log seems to do that already.\r
240         }\r
241 \r
242         void Timer::initTimer(bool usePerformanceTimer)\r
243         {\r
244                 initVirtualTimer();\r
245         }\r
246 \r
247         u32 Timer::getRealTime()\r
248         {\r
249         double time = emscripten_get_now();\r
250         return (u32)(time);\r
251         }\r
252 } // end namespace os\r
253 \r
254 #else\r
255 \r
256 // ----------------------------------------------------------------\r
257 // linux/ansi version\r
258 // ----------------------------------------------------------------\r
259 \r
260 #include <stdio.h>\r
261 #include <time.h>\r
262 #include <sys/time.h>\r
263 \r
264 namespace irr\r
265 {\r
266 namespace os\r
267 {\r
268 \r
269         //! prints a debuginfo string\r
270         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
271         {\r
272                 printf("%s\n", message);\r
273         }\r
274 \r
275         void Timer::initTimer(bool usePerformanceTimer)\r
276         {\r
277                 initVirtualTimer();\r
278         }\r
279 \r
280         u32 Timer::getRealTime()\r
281         {\r
282                 timeval tv;\r
283                 gettimeofday(&tv, 0);\r
284                 return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000);\r
285         }\r
286 } // end namespace os\r
287 \r
288 #endif // end linux / emscripten / android / windows\r
289 \r
290 namespace os\r
291 {\r
292         // The platform independent implementation of the printer\r
293         ILogger* Printer::Logger = 0;\r
294 \r
295         void Printer::log(const c8* message, ELOG_LEVEL ll)\r
296         {\r
297                 if (Logger)\r
298                         Logger->log(message, ll);\r
299         }\r
300 \r
301         void Printer::log(const wchar_t* message, ELOG_LEVEL ll)\r
302         {\r
303                 if (Logger)\r
304                         Logger->log(message, ll);\r
305         }\r
306 \r
307         void Printer::log(const c8* message, const c8* hint, ELOG_LEVEL ll)\r
308         {\r
309                 if (Logger)\r
310                         Logger->log(message, hint, ll);\r
311         }\r
312 \r
313         void Printer::log(const c8* message, const io::path& hint, ELOG_LEVEL ll)\r
314         {\r
315                 if (Logger)\r
316                         Logger->log(message, hint.c_str(), ll);\r
317         }\r
318 \r
319         // our Randomizer is not really os specific, so we\r
320         // code one for all, which should work on every platform the same,\r
321         // which is desirable.\r
322 \r
323         s32 Randomizer::seed = 0x0f0f0f0f;\r
324 \r
325         //! generates a pseudo random number\r
326         s32 Randomizer::rand()\r
327         {\r
328                 // (a*seed)%m with Schrage's method\r
329                 seed = a * (seed%q) - r* (seed/q);\r
330                 if (seed<1)\r
331                         seed += m;\r
332 \r
333                 return seed-1;  // -1 because we want it to start at 0\r
334         }\r
335 \r
336         //! generates a pseudo random number\r
337         f32 Randomizer::frand()\r
338         {\r
339                 return rand()*(1.f/rMax);\r
340         }\r
341 \r
342         s32 Randomizer::randMax()\r
343         {\r
344                 return rMax;\r
345         }\r
346 \r
347         //! resets the randomizer\r
348         void Randomizer::reset(s32 value)\r
349         {\r
350                 if (value<0)\r
351                         seed = value+m;\r
352                 else if ( value == 0 || value == m)\r
353                         seed = 1;\r
354                 else\r
355                         seed = value;\r
356         }\r
357 \r
358 \r
359         // ------------------------------------------------------\r
360         // virtual timer implementation\r
361 \r
362         f32 Timer::VirtualTimerSpeed = 1.0f;\r
363         s32 Timer::VirtualTimerStopCounter = 0;\r
364         u32 Timer::LastVirtualTime = 0;\r
365         u32 Timer::StartRealTime = 0;\r
366         u32 Timer::StaticTime = 0;\r
367 \r
368         //! Get real time and date in calendar form\r
369         ITimer::RealTimeDate Timer::getRealTimeAndDate()\r
370         {\r
371                 time_t rawtime;\r
372                 time(&rawtime);\r
373 \r
374                 struct tm * timeinfo;\r
375                 timeinfo = localtime(&rawtime);\r
376 \r
377                 // init with all 0 to indicate error\r
378                 ITimer::RealTimeDate date;\r
379                 memset(&date, 0, sizeof(date));\r
380                 // at least Windows returns NULL on some illegal dates\r
381                 if (timeinfo)\r
382                 {\r
383                         // set useful values if succeeded\r
384                         date.Hour=(u32)timeinfo->tm_hour;\r
385                         date.Minute=(u32)timeinfo->tm_min;\r
386                         date.Second=(u32)timeinfo->tm_sec;\r
387                         date.Day=(u32)timeinfo->tm_mday;\r
388                         date.Month=(u32)timeinfo->tm_mon+1;\r
389                         date.Year=(u32)timeinfo->tm_year+1900;\r
390                         date.Weekday=(ITimer::EWeekday)timeinfo->tm_wday;\r
391                         date.Yearday=(u32)timeinfo->tm_yday+1;\r
392                         date.IsDST=timeinfo->tm_isdst != 0;\r
393                 }\r
394                 return date;\r
395         }\r
396 \r
397         //! returns current virtual time\r
398         u32 Timer::getTime()\r
399         {\r
400                 if (isStopped())\r
401                         return LastVirtualTime;\r
402 \r
403                 return LastVirtualTime + (u32)((StaticTime - StartRealTime) * VirtualTimerSpeed);\r
404         }\r
405 \r
406         //! ticks, advances the virtual timer\r
407         void Timer::tick()\r
408         {\r
409                 StaticTime = getRealTime();\r
410         }\r
411 \r
412         //! sets the current virtual time\r
413         void Timer::setTime(u32 time)\r
414         {\r
415                 StaticTime = getRealTime();\r
416                 LastVirtualTime = time;\r
417                 StartRealTime = StaticTime;\r
418         }\r
419 \r
420         //! stops the virtual timer\r
421         void Timer::stopTimer()\r
422         {\r
423                 if (!isStopped())\r
424                 {\r
425                         // stop the virtual timer\r
426                         LastVirtualTime = getTime();\r
427                 }\r
428 \r
429                 --VirtualTimerStopCounter;\r
430         }\r
431 \r
432         //! starts the virtual timer\r
433         void Timer::startTimer()\r
434         {\r
435                 ++VirtualTimerStopCounter;\r
436 \r
437                 if (!isStopped())\r
438                 {\r
439                         // restart virtual timer\r
440                         setTime(LastVirtualTime);\r
441                 }\r
442         }\r
443 \r
444         //! sets the speed of the virtual timer\r
445         void Timer::setSpeed(f32 speed)\r
446         {\r
447                 setTime(getTime());\r
448 \r
449                 VirtualTimerSpeed = speed;\r
450                 if (VirtualTimerSpeed < 0.0f)\r
451                         VirtualTimerSpeed = 0.0f;\r
452         }\r
453 \r
454         //! gets the speed of the virtual timer\r
455         f32 Timer::getSpeed()\r
456         {\r
457                 return VirtualTimerSpeed;\r
458         }\r
459 \r
460         //! returns if the timer currently is stopped\r
461         bool Timer::isStopped()\r
462         {\r
463                 return VirtualTimerStopCounter < 0;\r
464         }\r
465 \r
466         void Timer::initVirtualTimer()\r
467         {\r
468                 StaticTime = getRealTime();\r
469                 StartRealTime = StaticTime;\r
470         }\r
471 \r
472 } // end namespace os\r
473 } // end namespace irr\r
474 \r
475 \r