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