upgrade SDL to version 2.0.8
[platform/upstream/SDL.git] / src / SDL.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2018 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 #endif
26
27 /* Initialization code for SDL */
28
29 #include "SDL.h"
30 #include "SDL_bits.h"
31 #include "SDL_revision.h"
32 #include "SDL_assert_c.h"
33 #include "events/SDL_events_c.h"
34 #include "haptic/SDL_haptic_c.h"
35 #include "joystick/SDL_joystick_c.h"
36
37 /* Initialization/Cleanup routines */
38 #if !SDL_TIMERS_DISABLED
39 # include "timer/SDL_timer_c.h"
40 #endif
41 #if SDL_VIDEO_DRIVER_WINDOWS
42 extern int SDL_HelperWindowCreate(void);
43 extern int SDL_HelperWindowDestroy(void);
44 #endif
45
46
47 /* The initialized subsystems */
48 #ifdef SDL_MAIN_NEEDED
49 static SDL_bool SDL_MainIsReady = SDL_FALSE;
50 #else
51 static SDL_bool SDL_MainIsReady = SDL_TRUE;
52 #endif
53 static SDL_bool SDL_bInMainQuit = SDL_FALSE;
54 static Uint8 SDL_SubsystemRefCount[ 32 ];
55
56 /* Private helper to increment a subsystem's ref counter. */
57 static void
58 SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)
59 {
60     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
61     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
62     ++SDL_SubsystemRefCount[subsystem_index];
63 }
64
65 /* Private helper to decrement a subsystem's ref counter. */
66 static void
67 SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
68 {
69     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
70     if (SDL_SubsystemRefCount[subsystem_index] > 0) {
71         --SDL_SubsystemRefCount[subsystem_index];
72     }
73 }
74
75 /* Private helper to check if a system needs init. */
76 static SDL_bool
77 SDL_PrivateShouldInitSubsystem(Uint32 subsystem)
78 {
79     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
80     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
81     return (SDL_SubsystemRefCount[subsystem_index] == 0) ? SDL_TRUE : SDL_FALSE;
82 }
83
84 /* Private helper to check if a system needs to be quit. */
85 static SDL_bool
86 SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) {
87     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
88     if (SDL_SubsystemRefCount[subsystem_index] == 0) {
89       return SDL_FALSE;
90     }
91
92     /* If we're in SDL_Quit, we shut down every subsystem, even if refcount
93      * isn't zero.
94      */
95     return (SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE;
96 }
97
98 void
99 SDL_SetMainReady(void)
100 {
101     SDL_MainIsReady = SDL_TRUE;
102 }
103
104 int
105 SDL_InitSubSystem(Uint32 flags)
106 {
107     if (!SDL_MainIsReady) {
108         SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
109         return -1;
110     }
111
112     /* Clear the error message */
113     SDL_ClearError();
114
115     if ((flags & SDL_INIT_GAMECONTROLLER)) {
116         /* game controller implies joystick */
117         flags |= SDL_INIT_JOYSTICK;
118     }
119
120     if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
121         /* video or joystick implies events */
122         flags |= SDL_INIT_EVENTS;
123     }
124
125 #if SDL_VIDEO_DRIVER_WINDOWS
126         if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
127                 if (SDL_HelperWindowCreate() < 0) {
128                         return -1;
129                 }
130         }
131 #endif
132
133 #if !SDL_TIMERS_DISABLED
134     SDL_TicksInit();
135 #endif
136
137     /* Initialize the event subsystem */
138     if ((flags & SDL_INIT_EVENTS)) {
139 #if !SDL_EVENTS_DISABLED
140         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) {
141             if (SDL_StartEventLoop() < 0) {
142                 return (-1);
143             }
144             SDL_QuitInit();
145         }
146         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS);
147 #else
148         return SDL_SetError("SDL not built with events support");
149 #endif
150     }
151
152     /* Initialize the timer subsystem */
153     if ((flags & SDL_INIT_TIMER)){
154 #if !SDL_TIMERS_DISABLED
155         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_TIMER)) {
156             if (SDL_TimerInit() < 0) {
157                 return (-1);
158             }
159         }
160         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_TIMER);
161 #else
162         return SDL_SetError("SDL not built with timer support");
163 #endif
164     }
165
166     /* Initialize the video subsystem */
167     if ((flags & SDL_INIT_VIDEO)){
168 #if !SDL_VIDEO_DISABLED
169         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_VIDEO)) {
170             if (SDL_VideoInit(NULL) < 0) {
171                 return (-1);
172             }
173         }
174         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_VIDEO);
175 #else
176         return SDL_SetError("SDL not built with video support");
177 #endif
178     }
179
180     /* Initialize the audio subsystem */
181     if ((flags & SDL_INIT_AUDIO)){
182 #if !SDL_AUDIO_DISABLED
183         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_AUDIO)) {
184             if (SDL_AudioInit(NULL) < 0) {
185                 return (-1);
186             }
187         }
188         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_AUDIO);
189 #else
190         return SDL_SetError("SDL not built with audio support");
191 #endif
192     }
193
194     /* Initialize the joystick subsystem */
195     if ((flags & SDL_INIT_JOYSTICK)){
196 #if !SDL_JOYSTICK_DISABLED
197         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
198            if (SDL_JoystickInit() < 0) {
199                return (-1);
200            }
201         }
202         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_JOYSTICK);
203 #else
204         return SDL_SetError("SDL not built with joystick support");
205 #endif
206     }
207
208     if ((flags & SDL_INIT_GAMECONTROLLER)){
209 #if !SDL_JOYSTICK_DISABLED
210         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_GAMECONTROLLER)) {
211             if (SDL_GameControllerInit() < 0) {
212                 return (-1);
213             }
214         }
215         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_GAMECONTROLLER);
216 #else
217         return SDL_SetError("SDL not built with joystick support");
218 #endif
219     }
220
221     /* Initialize the haptic subsystem */
222     if ((flags & SDL_INIT_HAPTIC)){
223 #if !SDL_HAPTIC_DISABLED
224         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_HAPTIC)) {
225             if (SDL_HapticInit() < 0) {
226                 return (-1);
227             }
228         }
229         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_HAPTIC);
230 #else
231         return SDL_SetError("SDL not built with haptic (force feedback) support");
232 #endif
233     }
234
235     return (0);
236 }
237
238 int
239 SDL_Init(Uint32 flags)
240 {
241     return SDL_InitSubSystem(flags);
242 }
243
244 void
245 SDL_QuitSubSystem(Uint32 flags)
246 {
247     /* Shut down requested initialized subsystems */
248 #if !SDL_JOYSTICK_DISABLED
249     if ((flags & SDL_INIT_GAMECONTROLLER)) {
250         /* game controller implies joystick */
251         flags |= SDL_INIT_JOYSTICK;
252
253         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) {
254             SDL_GameControllerQuit();
255         }
256         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_GAMECONTROLLER);
257     }
258
259     if ((flags & SDL_INIT_JOYSTICK)) {
260         /* joystick implies events */
261         flags |= SDL_INIT_EVENTS;
262
263         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
264             SDL_JoystickQuit();
265         }
266         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_JOYSTICK);
267     }
268 #endif
269
270 #if !SDL_HAPTIC_DISABLED
271     if ((flags & SDL_INIT_HAPTIC)) {
272         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
273             SDL_HapticQuit();
274         }
275         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_HAPTIC);
276     }
277 #endif
278
279 #if !SDL_AUDIO_DISABLED
280     if ((flags & SDL_INIT_AUDIO)) {
281         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) {
282             SDL_AudioQuit();
283         }
284         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_AUDIO);
285     }
286 #endif
287
288 #if !SDL_VIDEO_DISABLED
289     if ((flags & SDL_INIT_VIDEO)) {
290         /* video implies events */
291         flags |= SDL_INIT_EVENTS;
292
293         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) {
294             SDL_VideoQuit();
295         }
296         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_VIDEO);
297     }
298 #endif
299
300 #if !SDL_TIMERS_DISABLED
301     if ((flags & SDL_INIT_TIMER)) {
302         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_TIMER)) {
303             SDL_TimerQuit();
304         }
305         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER);
306     }
307 #endif
308
309 #if !SDL_EVENTS_DISABLED
310     if ((flags & SDL_INIT_EVENTS)) {
311         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) {
312             SDL_QuitQuit();
313             SDL_StopEventLoop();
314         }
315         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS);
316     }
317 #endif
318 }
319
320 Uint32
321 SDL_WasInit(Uint32 flags)
322 {
323     int i;
324     int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
325     Uint32 initialized = 0;
326
327     if (!flags) {
328         flags = SDL_INIT_EVERYTHING;
329     }
330
331     num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
332
333     /* Iterate over each bit in flags, and check the matching subsystem. */
334     for (i = 0; i < num_subsystems; ++i) {
335         if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
336             initialized |= (1 << i);
337         }
338
339         flags >>= 1;
340     }
341
342     return initialized;
343 }
344
345 void
346 SDL_Quit(void)
347 {
348     SDL_bInMainQuit = SDL_TRUE;
349
350     /* Quit all subsystems */
351 #if SDL_VIDEO_DRIVER_WINDOWS
352     SDL_HelperWindowDestroy();
353 #endif
354     SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
355
356 #if !SDL_TIMERS_DISABLED
357     SDL_TicksQuit();
358 #endif
359
360     SDL_ClearHints();
361     SDL_AssertionsQuit();
362     SDL_LogResetPriorities();
363
364     /* Now that every subsystem has been quit, we reset the subsystem refcount
365      * and the list of initialized subsystems.
366      */
367     SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
368
369     SDL_bInMainQuit = SDL_FALSE;
370 }
371
372 /* Get the library version number */
373 void
374 SDL_GetVersion(SDL_version * ver)
375 {
376     SDL_VERSION(ver);
377 }
378
379 /* Get the library source revision */
380 const char *
381 SDL_GetRevision(void)
382 {
383     return SDL_REVISION;
384 }
385
386 /* Get the library source revision number */
387 int
388 SDL_GetRevisionNumber(void)
389 {
390     return SDL_REVISION_NUMBER;
391 }
392
393 /* Get the name of the platform */
394 const char *
395 SDL_GetPlatform()
396 {
397 #if __AIX__
398     return "AIX";
399 #elif __ANDROID__
400     return "Android";
401 #elif __BSDI__
402     return "BSDI";
403 #elif __DREAMCAST__
404     return "Dreamcast";
405 #elif __EMSCRIPTEN__
406     return "Emscripten";
407 #elif __FREEBSD__
408     return "FreeBSD";
409 #elif __HAIKU__
410     return "Haiku";
411 #elif __HPUX__
412     return "HP-UX";
413 #elif __IRIX__
414     return "Irix";
415 #elif __LINUX__
416     return "Linux";
417 #elif __MINT__
418     return "Atari MiNT";
419 #elif __MACOS__
420     return "MacOS Classic";
421 #elif __MACOSX__
422     return "Mac OS X";
423 #elif __NACL__
424     return "NaCl";
425 #elif __NETBSD__
426     return "NetBSD";
427 #elif __OPENBSD__
428     return "OpenBSD";
429 #elif __OS2__
430     return "OS/2";
431 #elif __OSF__
432     return "OSF/1";
433 #elif __QNXNTO__
434     return "QNX Neutrino";
435 #elif __RISCOS__
436     return "RISC OS";
437 #elif __SOLARIS__
438     return "Solaris";
439 #elif __WIN32__
440     return "Windows";
441 #elif __WINRT__
442     return "WinRT";
443 #elif __TVOS__
444     return "tvOS";
445 #elif __IPHONEOS__
446     return "iOS";
447 #elif __PSP__
448     return "PlayStation Portable";
449 #elif __TIZEN__
450     return "Tizen";
451 #else
452     return "Unknown (see SDL_platform.h)";
453 #endif
454 }
455
456 #if defined(__WIN32__)
457
458 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
459 /* Need to include DllMain() on Watcom C for some reason.. */
460
461 BOOL APIENTRY
462 _DllMainCRTStartup(HANDLE hModule,
463                    DWORD ul_reason_for_call, LPVOID lpReserved)
464 {
465     switch (ul_reason_for_call) {
466     case DLL_PROCESS_ATTACH:
467     case DLL_THREAD_ATTACH:
468     case DLL_THREAD_DETACH:
469     case DLL_PROCESS_DETACH:
470         break;
471     }
472     return TRUE;
473 }
474 #endif /* Building DLL */
475
476 #endif /* __WIN32__ */
477
478 /* vi: set sts=4 ts=4 sw=4 expandtab: */