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
SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)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
SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)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
SDL_PrivateShouldInitSubsystem(Uint32 subsystem)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
SDL_PrivateShouldQuitSubsystem(Uint32 subsystem)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
SDL_SetMainReady(void)102 SDL_SetMainReady(void)
103 {
104 SDL_MainIsReady = SDL_TRUE;
105 }
106
107 int
SDL_InitSubSystem(Uint32 flags)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 ((flags & SDL_INIT_GAMECONTROLLER)) {
119 /* game controller implies joystick */
120 flags |= SDL_INIT_JOYSTICK;
121 }
122
123 if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
124 /* video or joystick implies events */
125 flags |= SDL_INIT_EVENTS;
126 }
127
128 #if SDL_VIDEO_DRIVER_WINDOWS
129 if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
130 if (SDL_HelperWindowCreate() < 0) {
131 return -1;
132 }
133 }
134 #endif
135
136 #if !SDL_TIMERS_DISABLED
137 SDL_TicksInit();
138 #endif
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
SDL_Init(Uint32 flags)242 SDL_Init(Uint32 flags)
243 {
244 return SDL_InitSubSystem(flags);
245 }
246
247 void
SDL_QuitSubSystem(Uint32 flags)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
SDL_WasInit(Uint32 flags)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
SDL_Quit(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
SDL_GetVersion(SDL_version * ver)377 SDL_GetVersion(SDL_version * ver)
378 {
379 SDL_VERSION(ver);
380 }
381
382 /* Get the library source revision */
383 const char *
SDL_GetRevision(void)384 SDL_GetRevision(void)
385 {
386 return SDL_REVISION;
387 }
388
389 /* Get the library source revision number */
390 int
SDL_GetRevisionNumber(void)391 SDL_GetRevisionNumber(void)
392 {
393 return SDL_REVISION_NUMBER;
394 }
395
396 /* Get the name of the platform */
397 const char *
SDL_GetPlatform()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 __TVOS__
447 return "tvOS";
448 #elif __IPHONEOS__
449 return "iOS";
450 #elif __PSP__
451 return "PlayStation Portable";
452 #else
453 return "Unknown (see SDL_platform.h)";
454 #endif
455 }
456
457 #if defined(__WIN32__)
458
459 #if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL))
460 /* Need to include DllMain() on Watcom C for some reason.. */
461
462 BOOL APIENTRY
_DllMainCRTStartup(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)463 _DllMainCRTStartup(HANDLE hModule,
464 DWORD ul_reason_for_call, LPVOID lpReserved)
465 {
466 switch (ul_reason_for_call) {
467 case DLL_PROCESS_ATTACH:
468 case DLL_THREAD_ATTACH:
469 case DLL_THREAD_DETACH:
470 case DLL_PROCESS_DETACH:
471 break;
472 }
473 return TRUE;
474 }
475 #endif /* building DLL with Watcom C */
476
477 #endif /* __WIN32__ */
478
479 /* vi: set sts=4 ts=4 sw=4 expandtab: */
480