Change std:vector to eina_array
[platform/upstream/SDL.git] / src / SDL.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "./SDL_internal.h"
22
23 #if defined(__WIN32__)
24 #include "core/windows/SDL_windows.h"
25 #elif defined(__OS2__)
26 #include <stdlib.h> /* For _exit() */
27 #elif !defined(__WINRT__)
28 #include <unistd.h> /* For _exit(), etc. */
29 #endif
30 #if defined(__OS2__)
31 #include "core/os2/SDL_os2.h"
32 #endif
33 #if SDL_THREAD_OS2
34 #include "thread/os2/SDL_systls_c.h"
35 #endif
36
37 #if defined(__EMSCRIPTEN__)
38 #include <emscripten.h>
39 #endif
40
41 /* Initialization code for SDL */
42
43 #include "SDL.h"
44 #include "SDL_bits.h"
45 #include "SDL_revision.h"
46 #include "SDL_assert_c.h"
47 #include "events/SDL_events_c.h"
48 #include "haptic/SDL_haptic_c.h"
49 #include "joystick/SDL_joystick_c.h"
50 #include "sensor/SDL_sensor_c.h"
51
52 /* Initialization/Cleanup routines */
53 #if !SDL_TIMERS_DISABLED
54 # include "timer/SDL_timer_c.h"
55 #endif
56 #if SDL_VIDEO_DRIVER_WINDOWS
57 extern int SDL_HelperWindowCreate(void);
58 extern int SDL_HelperWindowDestroy(void);
59 #endif
60
61
62 /* This is not declared in any header, although it is shared between some
63     parts of SDL, because we don't want anything calling it without an
64     extremely good reason. */
65 extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
66 SDL_NORETURN void SDL_ExitProcess(int exitcode)
67 {
68 #ifdef __WIN32__
69     /* "if you do not know the state of all threads in your process, it is
70        better to call TerminateProcess than ExitProcess"
71        https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */
72     TerminateProcess(GetCurrentProcess(), exitcode);
73     /* MingW doesn't have TerminateProcess marked as noreturn, so add an
74        ExitProcess here that will never be reached but make MingW happy. */
75     ExitProcess(exitcode);
76 #elif defined(__EMSCRIPTEN__)
77     emscripten_cancel_main_loop();  /* this should "kill" the app. */
78     emscripten_force_exit(exitcode);  /* this should "kill" the app. */
79     exit(exitcode);
80 #elif defined(__HAIKU__)  /* Haiku has _Exit, but it's not marked noreturn. */
81     _exit(exitcode);
82 #elif defined(HAVE__EXIT) /* Upper case _Exit() */
83     _Exit(exitcode);
84 #else
85     _exit(exitcode);
86 #endif
87 }
88
89
90 /* The initialized subsystems */
91 #ifdef SDL_MAIN_NEEDED
92 static SDL_bool SDL_MainIsReady = SDL_FALSE;
93 #else
94 static SDL_bool SDL_MainIsReady = SDL_TRUE;
95 #endif
96 static SDL_bool SDL_bInMainQuit = SDL_FALSE;
97 static Uint8 SDL_SubsystemRefCount[ 32 ];
98
99 /* Private helper to increment a subsystem's ref counter. */
100 static void
101 SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)
102 {
103     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
104     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
105     ++SDL_SubsystemRefCount[subsystem_index];
106 }
107
108 /* Private helper to decrement a subsystem's ref counter. */
109 static void
110 SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
111 {
112     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
113     if (SDL_SubsystemRefCount[subsystem_index] > 0) {
114         --SDL_SubsystemRefCount[subsystem_index];
115     }
116 }
117
118 /* Private helper to check if a system needs init. */
119 static SDL_bool
120 SDL_PrivateShouldInitSubsystem(Uint32 subsystem)
121 {
122     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
123     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
124     return (SDL_SubsystemRefCount[subsystem_index] == 0) ? SDL_TRUE : SDL_FALSE;
125 }
126
127 /* Private helper to check if a system needs to be quit. */
128 static SDL_bool
129 SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) {
130     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
131     if (SDL_SubsystemRefCount[subsystem_index] == 0) {
132       return SDL_FALSE;
133     }
134
135     /* If we're in SDL_Quit, we shut down every subsystem, even if refcount
136      * isn't zero.
137      */
138     return (SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE;
139 }
140
141 void
142 SDL_SetMainReady(void)
143 {
144     SDL_MainIsReady = SDL_TRUE;
145 }
146
147 int
148 SDL_InitSubSystem(Uint32 flags)
149 {
150     if (!SDL_MainIsReady) {
151         SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
152         return -1;
153     }
154
155 #if __TIZEN__
156     // Initialize with null input param in Tizen
157     if ((flags & SDL_INIT_VIDEO)){
158         SDL_Log("SDL_InitSubSystem: call SDL_tizen_app_init for null argument\n");
159         SDL_tizen_app_init(0, NULL);
160     }
161 #endif
162
163     /* Clear the error message */
164     SDL_ClearError();
165
166     if ((flags & SDL_INIT_GAMECONTROLLER)) {
167         /* game controller implies joystick */
168         flags |= SDL_INIT_JOYSTICK;
169     }
170
171     if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
172         /* video or joystick implies events */
173         flags |= SDL_INIT_EVENTS;
174     }
175
176 #if SDL_THREAD_OS2
177     SDL_OS2TLSAlloc(); /* thread/os2/SDL_systls.c */
178 #endif
179
180 #if SDL_VIDEO_DRIVER_WINDOWS
181     if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
182         if (SDL_HelperWindowCreate() < 0) {
183             return -1;
184         }
185     }
186 #endif
187
188 #if !SDL_TIMERS_DISABLED
189     SDL_TicksInit();
190 #endif
191
192     /* Initialize the event subsystem */
193     if ((flags & SDL_INIT_EVENTS)) {
194 #if !SDL_EVENTS_DISABLED
195         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) {
196             if (SDL_EventsInit() < 0) {
197                 return (-1);
198             }
199         }
200         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS);
201 #else
202         return SDL_SetError("SDL not built with events support");
203 #endif
204     }
205
206     /* Initialize the timer subsystem */
207     if ((flags & SDL_INIT_TIMER)){
208 #if !SDL_TIMERS_DISABLED
209         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_TIMER)) {
210             if (SDL_TimerInit() < 0) {
211                 return (-1);
212             }
213         }
214         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_TIMER);
215 #else
216         return SDL_SetError("SDL not built with timer support");
217 #endif
218     }
219
220     /* Initialize the video subsystem */
221     if ((flags & SDL_INIT_VIDEO)){
222 #if !SDL_VIDEO_DISABLED
223         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_VIDEO)) {
224             if (SDL_VideoInit(NULL) < 0) {
225                 return (-1);
226             }
227         }
228         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_VIDEO);
229 #else
230         return SDL_SetError("SDL not built with video support");
231 #endif
232     }
233
234     /* Initialize the audio subsystem */
235     if ((flags & SDL_INIT_AUDIO)){
236 #if !SDL_AUDIO_DISABLED
237         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_AUDIO)) {
238             if (SDL_AudioInit(NULL) < 0) {
239                 return (-1);
240             }
241         }
242         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_AUDIO);
243 #else
244         return SDL_SetError("SDL not built with audio support");
245 #endif
246     }
247
248     /* Initialize the joystick subsystem */
249     if ((flags & SDL_INIT_JOYSTICK)){
250 #if !SDL_JOYSTICK_DISABLED
251         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
252            if (SDL_JoystickInit() < 0) {
253                return (-1);
254            }
255         }
256         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_JOYSTICK);
257 #else
258         return SDL_SetError("SDL not built with joystick support");
259 #endif
260     }
261
262     if ((flags & SDL_INIT_GAMECONTROLLER)){
263 #if !SDL_JOYSTICK_DISABLED
264         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_GAMECONTROLLER)) {
265             if (SDL_GameControllerInit() < 0) {
266                 return (-1);
267             }
268         }
269         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_GAMECONTROLLER);
270 #else
271         return SDL_SetError("SDL not built with joystick support");
272 #endif
273     }
274
275     /* Initialize the haptic subsystem */
276     if ((flags & SDL_INIT_HAPTIC)){
277 #if !SDL_HAPTIC_DISABLED
278         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_HAPTIC)) {
279             if (SDL_HapticInit() < 0) {
280                 return (-1);
281             }
282         }
283         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_HAPTIC);
284 #else
285         return SDL_SetError("SDL not built with haptic (force feedback) support");
286 #endif
287     }
288
289     /* Initialize the sensor subsystem */
290     if ((flags & SDL_INIT_SENSOR)){
291 #if !SDL_SENSOR_DISABLED
292         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_SENSOR)) {
293             if (SDL_SensorInit() < 0) {
294                 return (-1);
295             }
296         }
297         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_SENSOR);
298 #else
299         return SDL_SetError("SDL not built with sensor support");
300 #endif
301     }
302
303     return (0);
304 }
305
306 int
307 SDL_Init(Uint32 flags)
308 {
309     return SDL_InitSubSystem(flags);
310 }
311
312 void
313 SDL_QuitSubSystem(Uint32 flags)
314 {
315 #if SDL_THREAD_OS2
316     SDL_OS2TLSFree(); /* thread/os2/SDL_systls.c */
317 #endif
318 #if defined(__OS2__)
319     SDL_OS2Quit();
320 #endif
321
322     /* Shut down requested initialized subsystems */
323 #if !SDL_SENSOR_DISABLED
324     if ((flags & SDL_INIT_SENSOR)) {
325         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_SENSOR)) {
326             SDL_SensorQuit();
327         }
328         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_SENSOR);
329     }
330 #endif
331
332 #if !SDL_JOYSTICK_DISABLED
333     if ((flags & SDL_INIT_GAMECONTROLLER)) {
334         /* game controller implies joystick */
335         flags |= SDL_INIT_JOYSTICK;
336
337         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) {
338             SDL_GameControllerQuit();
339         }
340         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_GAMECONTROLLER);
341     }
342
343     if ((flags & SDL_INIT_JOYSTICK)) {
344         /* joystick implies events */
345         flags |= SDL_INIT_EVENTS;
346
347         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
348             SDL_JoystickQuit();
349         }
350         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_JOYSTICK);
351     }
352 #endif
353
354 #if !SDL_HAPTIC_DISABLED
355     if ((flags & SDL_INIT_HAPTIC)) {
356         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
357             SDL_HapticQuit();
358         }
359         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_HAPTIC);
360     }
361 #endif
362
363 #if !SDL_AUDIO_DISABLED
364     if ((flags & SDL_INIT_AUDIO)) {
365         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) {
366             SDL_AudioQuit();
367         }
368         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_AUDIO);
369     }
370 #endif
371
372 #if !SDL_VIDEO_DISABLED
373     if ((flags & SDL_INIT_VIDEO)) {
374         /* video implies events */
375         flags |= SDL_INIT_EVENTS;
376
377         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) {
378             SDL_VideoQuit();
379         }
380         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_VIDEO);
381     }
382 #endif
383
384 #if !SDL_TIMERS_DISABLED
385     if ((flags & SDL_INIT_TIMER)) {
386         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_TIMER)) {
387             SDL_TimerQuit();
388         }
389         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER);
390     }
391 #endif
392
393 #if !SDL_EVENTS_DISABLED
394     if ((flags & SDL_INIT_EVENTS)) {
395         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) {
396             SDL_EventsQuit();
397         }
398         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS);
399     }
400 #endif
401 }
402
403 Uint32
404 SDL_WasInit(Uint32 flags)
405 {
406     int i;
407     int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
408     Uint32 initialized = 0;
409
410     /* Fast path for checking one flag */
411     if (SDL_HasExactlyOneBitSet32(flags)) {
412         int subsystem_index = SDL_MostSignificantBitIndex32(flags);
413         return SDL_SubsystemRefCount[subsystem_index] ? flags : 0;
414     }
415
416     if (!flags) {
417         flags = SDL_INIT_EVERYTHING;
418     }
419
420     num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
421
422     /* Iterate over each bit in flags, and check the matching subsystem. */
423     for (i = 0; i < num_subsystems; ++i) {
424         if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
425             initialized |= (1 << i);
426         }
427
428         flags >>= 1;
429     }
430
431     return initialized;
432 }
433
434 void
435 SDL_Quit(void)
436 {
437     SDL_bInMainQuit = SDL_TRUE;
438
439     /* Quit all subsystems */
440 #if SDL_VIDEO_DRIVER_WINDOWS
441     SDL_HelperWindowDestroy();
442 #endif
443     SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
444
445 #if !SDL_TIMERS_DISABLED
446     SDL_TicksQuit();
447 #endif
448
449     SDL_ClearHints();
450     SDL_AssertionsQuit();
451     SDL_LogResetPriorities();
452
453     /* Now that every subsystem has been quit, we reset the subsystem refcount
454      * and the list of initialized subsystems.
455      */
456     SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
457
458     SDL_bInMainQuit = SDL_FALSE;
459 }
460
461 /* Get the library version number */
462 void
463 SDL_GetVersion(SDL_version * ver)
464 {
465     SDL_VERSION(ver);
466 }
467
468 /* Get the library source revision */
469 const char *
470 SDL_GetRevision(void)
471 {
472     return SDL_REVISION;
473 }
474
475 /* Get the library source revision number */
476 int
477 SDL_GetRevisionNumber(void)
478 {
479     return SDL_REVISION_NUMBER;
480 }
481
482 /* Get the name of the platform */
483 const char *
484 SDL_GetPlatform()
485 {
486 #if __AIX__
487     return "AIX";
488 #elif __ANDROID__
489     return "Android";
490 #elif __BSDI__
491     return "BSDI";
492 #elif __DREAMCAST__
493     return "Dreamcast";
494 #elif __EMSCRIPTEN__
495     return "Emscripten";
496 #elif __FREEBSD__
497     return "FreeBSD";
498 #elif __HAIKU__
499     return "Haiku";
500 #elif __HPUX__
501     return "HP-UX";
502 #elif __IRIX__
503     return "Irix";
504 #elif __LINUX__
505     return "Linux";
506 #elif __MINT__
507     return "Atari MiNT";
508 #elif __MACOS__
509     return "MacOS Classic";
510 #elif __MACOSX__
511     return "Mac OS X";
512 #elif __NACL__
513     return "NaCl";
514 #elif __NETBSD__
515     return "NetBSD";
516 #elif __OPENBSD__
517     return "OpenBSD";
518 #elif __OS2__
519     return "OS/2";
520 #elif __OSF__
521     return "OSF/1";
522 #elif __QNXNTO__
523     return "QNX Neutrino";
524 #elif __RISCOS__
525     return "RISC OS";
526 #elif __SOLARIS__
527     return "Solaris";
528 #elif __WIN32__
529     return "Windows";
530 #elif __WINRT__
531     return "WinRT";
532 #elif __TVOS__
533     return "tvOS";
534 #elif __IPHONEOS__
535     return "iOS";
536 #elif __PSP__
537     return "PlayStation Portable";
538 #elif __TIZEN__
539     return "Tizen";
540 #else
541     return "Unknown (see SDL_platform.h)";
542 #endif
543 }
544
545 SDL_bool
546 SDL_IsTablet()
547 {
548 #if __ANDROID__
549     extern SDL_bool SDL_IsAndroidTablet(void);
550     return SDL_IsAndroidTablet();
551 #elif __IPHONEOS__
552     extern SDL_bool SDL_IsIPad(void);
553     return SDL_IsIPad();
554 #else
555     return SDL_FALSE;
556 #endif
557 }
558
559 #if defined(__WIN32__)
560
561 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
562 /* Need to include DllMain() on Watcom C for some reason.. */
563
564 BOOL APIENTRY
565 _DllMainCRTStartup(HANDLE hModule,
566                    DWORD ul_reason_for_call, LPVOID lpReserved)
567 {
568     switch (ul_reason_for_call) {
569     case DLL_PROCESS_ATTACH:
570     case DLL_THREAD_ATTACH:
571     case DLL_THREAD_DETACH:
572     case DLL_PROCESS_DETACH:
573         break;
574     }
575     return TRUE;
576 }
577 #endif /* Building DLL */
578
579 #endif /* __WIN32__ */
580
581 /* vi: set sts=4 ts=4 sw=4 expandtab: */