Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/SDL.c
9896 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
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
#include "SDL3/SDL_revision.h"
23
24
#if defined(SDL_PLATFORM_WINDOWS)
25
#include "core/windows/SDL_windows.h"
26
#else
27
#include <unistd.h> // _exit(), etc.
28
#endif
29
30
// this checks for HAVE_DBUS_DBUS_H internally.
31
#include "core/linux/SDL_dbus.h"
32
33
#ifdef SDL_PLATFORM_EMSCRIPTEN
34
#include <emscripten.h>
35
#endif
36
37
// Initialization code for SDL
38
39
#include "SDL_assert_c.h"
40
#include "SDL_hints_c.h"
41
#include "SDL_log_c.h"
42
#include "SDL_properties_c.h"
43
//#include "audio/SDL_sysaudio.h"
44
#include "events/SDL_events_c.h"
45
#include "haptic/SDL_haptic_c.h"
46
#include "joystick/SDL_gamepad_c.h"
47
#include "joystick/SDL_joystick_c.h"
48
#include "sensor/SDL_sensor_c.h"
49
#include "stdlib/SDL_getenv_c.h"
50
#include "thread/SDL_thread_c.h"
51
#ifdef SDL_PLATFORM_ANDROID
52
#include "core/android/SDL_android.h"
53
#endif
54
55
#define SDL_INIT_EVERYTHING ~0U
56
57
// Initialization/Cleanup routines
58
#include "timer/SDL_timer_c.h"
59
#ifdef SDL_VIDEO_DRIVER_WINDOWS
60
extern bool SDL_HelperWindowCreate(void);
61
extern void SDL_HelperWindowDestroy(void);
62
#endif
63
64
#ifdef SDL_BUILD_MAJOR_VERSION
65
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MAJOR_VERSION,
66
SDL_MAJOR_VERSION == SDL_BUILD_MAJOR_VERSION);
67
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MINOR_VERSION,
68
SDL_MINOR_VERSION == SDL_BUILD_MINOR_VERSION);
69
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MICRO_VERSION,
70
SDL_MICRO_VERSION == SDL_BUILD_MICRO_VERSION);
71
#endif
72
73
// Limited by its encoding in SDL_VERSIONNUM
74
SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_min, SDL_MAJOR_VERSION >= 0);
75
SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_max, SDL_MAJOR_VERSION <= 10);
76
SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_min, SDL_MINOR_VERSION >= 0);
77
SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_max, SDL_MINOR_VERSION <= 999);
78
SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_min, SDL_MICRO_VERSION >= 0);
79
SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_max, SDL_MICRO_VERSION <= 999);
80
81
/* This is not declared in any header, although it is shared between some
82
parts of SDL, because we don't want anything calling it without an
83
extremely good reason. */
84
extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
85
SDL_NORETURN void SDL_ExitProcess(int exitcode)
86
{
87
#if defined(SDL_PLATFORM_WINDOWS)
88
/* "if you do not know the state of all threads in your process, it is
89
better to call TerminateProcess than ExitProcess"
90
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */
91
TerminateProcess(GetCurrentProcess(), exitcode);
92
/* MingW doesn't have TerminateProcess marked as noreturn, so add an
93
ExitProcess here that will never be reached but make MingW happy. */
94
ExitProcess(exitcode);
95
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
96
emscripten_cancel_main_loop(); // this should "kill" the app.
97
emscripten_force_exit(exitcode); // this should "kill" the app.
98
exit(exitcode);
99
#elif defined(SDL_PLATFORM_HAIKU) // Haiku has _Exit, but it's not marked noreturn.
100
_exit(exitcode);
101
#elif defined(HAVE__EXIT) // Upper case _Exit()
102
_Exit(exitcode);
103
#else
104
_exit(exitcode);
105
#endif
106
}
107
108
// App metadata
109
110
bool SDL_SetAppMetadata(const char *appname, const char *appversion, const char *appidentifier)
111
{
112
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, appname);
113
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, appversion);
114
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, appidentifier);
115
return true;
116
}
117
118
static bool SDL_ValidMetadataProperty(const char *name)
119
{
120
if (!name || !*name) {
121
return false;
122
}
123
124
if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0 ||
125
SDL_strcmp(name, SDL_PROP_APP_METADATA_VERSION_STRING) == 0 ||
126
SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0 ||
127
SDL_strcmp(name, SDL_PROP_APP_METADATA_CREATOR_STRING) == 0 ||
128
SDL_strcmp(name, SDL_PROP_APP_METADATA_COPYRIGHT_STRING) == 0 ||
129
SDL_strcmp(name, SDL_PROP_APP_METADATA_URL_STRING) == 0 ||
130
SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) {
131
return true;
132
}
133
return false;
134
}
135
136
bool SDL_SetAppMetadataProperty(const char *name, const char *value)
137
{
138
if (!SDL_ValidMetadataProperty(name)) {
139
return SDL_InvalidParamError("name");
140
}
141
142
return SDL_SetStringProperty(SDL_GetGlobalProperties(), name, value);
143
}
144
145
const char *SDL_GetAppMetadataProperty(const char *name)
146
{
147
if (!SDL_ValidMetadataProperty(name)) {
148
SDL_InvalidParamError("name");
149
return NULL;
150
}
151
152
const char *value = NULL;
153
if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) {
154
value = SDL_GetHint(SDL_HINT_APP_NAME);
155
} else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0) {
156
value = SDL_GetHint(SDL_HINT_APP_ID);
157
}
158
if (!value || !*value) {
159
value = SDL_GetStringProperty(SDL_GetGlobalProperties(), name, NULL);
160
}
161
if (!value || !*value) {
162
if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) {
163
value = "SDL Application";
164
} else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) {
165
value = "application";
166
}
167
}
168
return value;
169
}
170
171
172
// The initialized subsystems
173
#ifdef SDL_MAIN_NEEDED
174
static bool SDL_MainIsReady = false;
175
#else
176
static bool SDL_MainIsReady = true;
177
#endif
178
static SDL_ThreadID SDL_MainThreadID = 0;
179
static bool SDL_bInMainQuit = false;
180
static Uint8 SDL_SubsystemRefCount[32];
181
182
// Private helper to increment a subsystem's ref counter.
183
static void SDL_IncrementSubsystemRefCount(Uint32 subsystem)
184
{
185
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
186
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
187
if (subsystem_index >= 0) {
188
++SDL_SubsystemRefCount[subsystem_index];
189
}
190
}
191
192
// Private helper to decrement a subsystem's ref counter.
193
static void SDL_DecrementSubsystemRefCount(Uint32 subsystem)
194
{
195
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
196
if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] > 0)) {
197
if (SDL_bInMainQuit) {
198
SDL_SubsystemRefCount[subsystem_index] = 0;
199
} else {
200
--SDL_SubsystemRefCount[subsystem_index];
201
}
202
}
203
}
204
205
// Private helper to check if a system needs init.
206
static bool SDL_ShouldInitSubsystem(Uint32 subsystem)
207
{
208
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
209
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
210
return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0));
211
}
212
213
// Private helper to check if a system needs to be quit.
214
static bool SDL_ShouldQuitSubsystem(Uint32 subsystem)
215
{
216
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
217
if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) {
218
return false;
219
}
220
221
/* If we're in SDL_Quit, we shut down every subsystem, even if refcount
222
* isn't zero.
223
*/
224
return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit);
225
}
226
227
/* Private helper to either increment's existing ref counter,
228
* or fully init a new subsystem. */
229
static bool SDL_InitOrIncrementSubsystem(Uint32 subsystem)
230
{
231
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
232
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
233
if (subsystem_index < 0) {
234
return false;
235
}
236
if (SDL_SubsystemRefCount[subsystem_index] > 0) {
237
++SDL_SubsystemRefCount[subsystem_index];
238
return true;
239
}
240
return SDL_InitSubSystem(subsystem);
241
}
242
243
void SDL_SetMainReady(void)
244
{
245
SDL_MainIsReady = true;
246
247
if (SDL_MainThreadID == 0) {
248
SDL_MainThreadID = SDL_GetCurrentThreadID();
249
}
250
}
251
252
bool SDL_IsMainThread(void)
253
{
254
if (SDL_MainThreadID == 0) {
255
// Not initialized yet?
256
return true;
257
}
258
if (SDL_MainThreadID == SDL_GetCurrentThreadID()) {
259
return true;
260
}
261
return false;
262
}
263
264
// Initialize all the subsystems that require initialization before threads start
265
void SDL_InitMainThread(void)
266
{
267
static bool done_info = false;
268
269
SDL_InitTLSData();
270
SDL_InitEnvironment();
271
SDL_InitTicks();
272
//SDL_InitFilesystem();
273
274
if (!done_info) {
275
const char *value;
276
277
value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING);
278
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App name: %s", value ? value : "<unspecified>");
279
value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING);
280
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App version: %s", value ? value : "<unspecified>");
281
value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING);
282
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App ID: %s", value ? value : "<unspecified>");
283
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "SDL revision: %s", SDL_REVISION);
284
285
done_info = true;
286
}
287
}
288
289
static void SDL_QuitMainThread(void)
290
{
291
//SDL_QuitFilesystem();
292
SDL_QuitTicks();
293
SDL_QuitEnvironment();
294
SDL_QuitTLSData();
295
}
296
297
bool SDL_InitSubSystem(SDL_InitFlags flags)
298
{
299
Uint32 flags_initialized = 0;
300
301
if (!SDL_MainIsReady) {
302
return SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
303
}
304
305
SDL_InitMainThread();
306
307
#ifdef SDL_USE_LIBDBUS
308
SDL_DBus_Init();
309
#endif
310
311
#ifdef SDL_VIDEO_DRIVER_WINDOWS
312
if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) {
313
if (!SDL_HelperWindowCreate()) {
314
goto quit_and_error;
315
}
316
}
317
#endif
318
319
// Initialize the event subsystem
320
if (flags & SDL_INIT_EVENTS) {
321
if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) {
322
SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS);
323
if (!SDL_InitEvents()) {
324
SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS);
325
goto quit_and_error;
326
}
327
} else {
328
SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS);
329
}
330
flags_initialized |= SDL_INIT_EVENTS;
331
}
332
333
// Initialize the video subsystem
334
if (flags & SDL_INIT_VIDEO) {
335
#ifndef SDL_VIDEO_DISABLED
336
if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) {
337
// video implies events
338
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
339
goto quit_and_error;
340
}
341
342
// We initialize video on the main thread
343
// On Apple platforms this is a requirement.
344
// On other platforms, this is the definition.
345
SDL_MainThreadID = SDL_GetCurrentThreadID();
346
347
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
348
if (!SDL_VideoInit(NULL)) {
349
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
350
SDL_PushError();
351
SDL_QuitSubSystem(SDL_INIT_EVENTS);
352
SDL_PopError();
353
goto quit_and_error;
354
}
355
} else {
356
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
357
}
358
flags_initialized |= SDL_INIT_VIDEO;
359
#else
360
SDL_SetError("SDL not built with video support");
361
goto quit_and_error;
362
#endif
363
}
364
365
// Initialize the audio subsystem
366
if (flags & SDL_INIT_AUDIO) {
367
#ifndef SDL_AUDIO_DISABLED
368
if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) {
369
// audio implies events
370
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
371
goto quit_and_error;
372
}
373
374
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
375
if (!SDL_InitAudio(NULL)) {
376
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
377
SDL_PushError();
378
SDL_QuitSubSystem(SDL_INIT_EVENTS);
379
SDL_PopError();
380
goto quit_and_error;
381
}
382
} else {
383
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
384
}
385
flags_initialized |= SDL_INIT_AUDIO;
386
#else
387
SDL_SetError("SDL not built with audio support");
388
goto quit_and_error;
389
#endif
390
}
391
392
// Initialize the joystick subsystem
393
if (flags & SDL_INIT_JOYSTICK) {
394
#ifndef SDL_JOYSTICK_DISABLED
395
if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
396
// joystick implies events
397
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
398
goto quit_and_error;
399
}
400
401
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
402
if (!SDL_InitJoysticks()) {
403
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
404
SDL_PushError();
405
SDL_QuitSubSystem(SDL_INIT_EVENTS);
406
SDL_PopError();
407
goto quit_and_error;
408
}
409
} else {
410
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
411
}
412
flags_initialized |= SDL_INIT_JOYSTICK;
413
#else
414
SDL_SetError("SDL not built with joystick support");
415
goto quit_and_error;
416
#endif
417
}
418
419
if (flags & SDL_INIT_GAMEPAD) {
420
#ifndef SDL_JOYSTICK_DISABLED
421
if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) {
422
// game controller implies joystick
423
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) {
424
goto quit_and_error;
425
}
426
427
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
428
if (!SDL_InitGamepads()) {
429
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
430
SDL_PushError();
431
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
432
SDL_PopError();
433
goto quit_and_error;
434
}
435
} else {
436
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
437
}
438
flags_initialized |= SDL_INIT_GAMEPAD;
439
#else
440
SDL_SetError("SDL not built with joystick support");
441
goto quit_and_error;
442
#endif
443
}
444
445
// Initialize the haptic subsystem
446
if (flags & SDL_INIT_HAPTIC) {
447
#ifndef SDL_HAPTIC_DISABLED
448
if (SDL_ShouldInitSubsystem(SDL_INIT_HAPTIC)) {
449
SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC);
450
if (!SDL_InitHaptics()) {
451
SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC);
452
goto quit_and_error;
453
}
454
} else {
455
SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC);
456
}
457
flags_initialized |= SDL_INIT_HAPTIC;
458
#else
459
SDL_SetError("SDL not built with haptic (force feedback) support");
460
goto quit_and_error;
461
#endif
462
}
463
464
// Initialize the sensor subsystem
465
if (flags & SDL_INIT_SENSOR) {
466
#ifndef SDL_SENSOR_DISABLED
467
if (SDL_ShouldInitSubsystem(SDL_INIT_SENSOR)) {
468
SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR);
469
if (!SDL_InitSensors()) {
470
SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR);
471
goto quit_and_error;
472
}
473
} else {
474
SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR);
475
}
476
flags_initialized |= SDL_INIT_SENSOR;
477
#else
478
SDL_SetError("SDL not built with sensor support");
479
goto quit_and_error;
480
#endif
481
}
482
483
// Initialize the camera subsystem
484
if (flags & SDL_INIT_CAMERA) {
485
#ifndef SDL_CAMERA_DISABLED
486
if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) {
487
// camera implies events
488
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
489
goto quit_and_error;
490
}
491
492
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
493
if (!SDL_CameraInit(NULL)) {
494
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
495
SDL_PushError();
496
SDL_QuitSubSystem(SDL_INIT_EVENTS);
497
SDL_PopError();
498
goto quit_and_error;
499
}
500
} else {
501
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
502
}
503
flags_initialized |= SDL_INIT_CAMERA;
504
#else
505
SDL_SetError("SDL not built with camera support");
506
goto quit_and_error;
507
#endif
508
}
509
510
(void)flags_initialized; // make static analysis happy, since this only gets used in error cases.
511
512
return SDL_ClearError();
513
514
quit_and_error:
515
{
516
SDL_PushError();
517
SDL_QuitSubSystem(flags_initialized);
518
SDL_PopError();
519
}
520
return false;
521
}
522
523
bool SDL_Init(SDL_InitFlags flags)
524
{
525
return SDL_InitSubSystem(flags);
526
}
527
528
void SDL_QuitSubSystem(SDL_InitFlags flags)
529
{
530
// Shut down requested initialized subsystems
531
532
#ifndef SDL_CAMERA_DISABLED
533
if (flags & SDL_INIT_CAMERA) {
534
if (SDL_ShouldQuitSubsystem(SDL_INIT_CAMERA)) {
535
SDL_QuitCamera();
536
// camera implies events
537
SDL_QuitSubSystem(SDL_INIT_EVENTS);
538
}
539
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
540
}
541
#endif
542
543
#ifndef SDL_SENSOR_DISABLED
544
if (flags & SDL_INIT_SENSOR) {
545
if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) {
546
SDL_QuitSensors();
547
}
548
SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR);
549
}
550
#endif
551
552
#ifndef SDL_JOYSTICK_DISABLED
553
if (flags & SDL_INIT_GAMEPAD) {
554
if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) {
555
SDL_QuitGamepads();
556
// game controller implies joystick
557
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
558
}
559
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
560
}
561
562
if (flags & SDL_INIT_JOYSTICK) {
563
if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
564
SDL_QuitJoysticks();
565
// joystick implies events
566
SDL_QuitSubSystem(SDL_INIT_EVENTS);
567
}
568
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
569
}
570
#endif
571
572
#ifndef SDL_HAPTIC_DISABLED
573
if (flags & SDL_INIT_HAPTIC) {
574
if (SDL_ShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
575
SDL_QuitHaptics();
576
}
577
SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC);
578
}
579
#endif
580
581
#ifndef SDL_AUDIO_DISABLED
582
if (flags & SDL_INIT_AUDIO) {
583
if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) {
584
SDL_QuitAudio();
585
// audio implies events
586
SDL_QuitSubSystem(SDL_INIT_EVENTS);
587
}
588
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
589
}
590
#endif
591
592
#ifndef SDL_VIDEO_DISABLED
593
if (flags & SDL_INIT_VIDEO) {
594
if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) {
595
SDL_QuitRender();
596
SDL_VideoQuit();
597
// video implies events
598
SDL_QuitSubSystem(SDL_INIT_EVENTS);
599
}
600
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
601
}
602
#endif
603
604
if (flags & SDL_INIT_EVENTS) {
605
if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) {
606
SDL_QuitEvents();
607
}
608
SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS);
609
}
610
}
611
612
Uint32 SDL_WasInit(SDL_InitFlags flags)
613
{
614
int i;
615
int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
616
Uint32 initialized = 0;
617
618
// Fast path for checking one flag
619
if (SDL_HasExactlyOneBitSet32(flags)) {
620
int subsystem_index = SDL_MostSignificantBitIndex32(flags);
621
return SDL_SubsystemRefCount[subsystem_index] ? flags : 0;
622
}
623
624
if (!flags) {
625
flags = SDL_INIT_EVERYTHING;
626
}
627
628
num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
629
630
// Iterate over each bit in flags, and check the matching subsystem.
631
for (i = 0; i < num_subsystems; ++i) {
632
if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
633
initialized |= (1 << i);
634
}
635
636
flags >>= 1;
637
}
638
639
return initialized;
640
}
641
642
void SDL_Quit(void)
643
{
644
SDL_bInMainQuit = true;
645
646
// Quit all subsystems
647
#ifdef SDL_VIDEO_DRIVER_WINDOWS
648
SDL_HelperWindowDestroy();
649
#endif
650
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
651
//SDL_CleanupTrays();
652
653
#ifdef SDL_USE_LIBDBUS
654
SDL_DBus_Quit();
655
#endif
656
657
SDL_QuitTimers();
658
//SDL_QuitAsyncIO();
659
660
SDL_SetObjectsInvalid();
661
SDL_AssertionsQuit();
662
663
//SDL_QuitPixelFormatDetails();
664
665
//SDL_QuitCPUInfo();
666
667
/* Now that every subsystem has been quit, we reset the subsystem refcount
668
* and the list of initialized subsystems.
669
*/
670
SDL_memset(SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount));
671
672
SDL_QuitLog();
673
SDL_QuitHints();
674
SDL_QuitProperties();
675
676
SDL_QuitMainThread();
677
678
SDL_bInMainQuit = false;
679
}
680
681
// Get the library version number
682
int SDL_GetVersion(void)
683
{
684
return SDL_VERSION;
685
}
686
687
// Get the library source revision
688
const char *SDL_GetRevision(void)
689
{
690
return SDL_REVISION;
691
}
692
693
// Get the name of the platform
694
const char *SDL_GetPlatform(void)
695
{
696
#if defined(SDL_PLATFORM_PRIVATE)
697
return SDL_PLATFORM_PRIVATE_NAME;
698
#elif defined(SDL_PLATFORM_AIX)
699
return "AIX";
700
#elif defined(SDL_PLATFORM_ANDROID)
701
return "Android";
702
#elif defined(SDL_PLATFORM_BSDI)
703
return "BSDI";
704
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
705
return "Emscripten";
706
#elif defined(SDL_PLATFORM_FREEBSD)
707
return "FreeBSD";
708
#elif defined(SDL_PLATFORM_HAIKU)
709
return "Haiku";
710
#elif defined(SDL_PLATFORM_HPUX)
711
return "HP-UX";
712
#elif defined(SDL_PLATFORM_IRIX)
713
return "Irix";
714
#elif defined(SDL_PLATFORM_LINUX)
715
return "Linux";
716
#elif defined(__MINT__)
717
return "Atari MiNT";
718
#elif defined(SDL_PLATFORM_MACOS)
719
return "macOS";
720
#elif defined(SDL_PLATFORM_NETBSD)
721
return "NetBSD";
722
#elif defined(SDL_PLATFORM_OPENBSD)
723
return "OpenBSD";
724
#elif defined(SDL_PLATFORM_OS2)
725
return "OS/2";
726
#elif defined(SDL_PLATFORM_OSF)
727
return "OSF/1";
728
#elif defined(SDL_PLATFORM_QNXNTO)
729
return "QNX Neutrino";
730
#elif defined(SDL_PLATFORM_RISCOS)
731
return "RISC OS";
732
#elif defined(SDL_PLATFORM_SOLARIS)
733
return "Solaris";
734
#elif defined(SDL_PLATFORM_WIN32)
735
return "Windows";
736
#elif defined(SDL_PLATFORM_WINGDK)
737
return "WinGDK";
738
#elif defined(SDL_PLATFORM_XBOXONE)
739
return "Xbox One";
740
#elif defined(SDL_PLATFORM_XBOXSERIES)
741
return "Xbox Series X|S";
742
#elif defined(SDL_PLATFORM_IOS)
743
return "iOS";
744
#elif defined(SDL_PLATFORM_TVOS)
745
return "tvOS";
746
#elif defined(SDL_PLATFORM_PS2)
747
return "PlayStation 2";
748
#elif defined(SDL_PLATFORM_PSP)
749
return "PlayStation Portable";
750
#elif defined(SDL_PLATFORM_VITA)
751
return "PlayStation Vita";
752
#elif defined(SDL_PLATFORM_3DS)
753
return "Nintendo 3DS";
754
#elif defined(__managarm__)
755
return "Managarm";
756
#else
757
return "Unknown (see SDL_platform.h)";
758
#endif
759
}
760
761
bool SDL_IsTablet(void)
762
{
763
#ifdef SDL_PLATFORM_ANDROID
764
return SDL_IsAndroidTablet();
765
#elif defined(SDL_PLATFORM_IOS)
766
extern bool SDL_IsIPad(void);
767
return SDL_IsIPad();
768
#else
769
return false;
770
#endif
771
}
772
773
bool SDL_IsTV(void)
774
{
775
#ifdef SDL_PLATFORM_ANDROID
776
return SDL_IsAndroidTV();
777
#elif defined(SDL_PLATFORM_IOS)
778
extern bool SDL_IsAppleTV(void);
779
return SDL_IsAppleTV();
780
#else
781
return false;
782
#endif
783
}
784
785
static SDL_Sandbox SDL_DetectSandbox(void)
786
{
787
#if defined(SDL_PLATFORM_LINUX)
788
if (access("/.flatpak-info", F_OK) == 0) {
789
return SDL_SANDBOX_FLATPAK;
790
}
791
792
/* For Snap, we check multiple variables because they might be set for
793
* unrelated reasons. This is the same thing WebKitGTK does. */
794
if (SDL_getenv("SNAP") && SDL_getenv("SNAP_NAME") && SDL_getenv("SNAP_REVISION")) {
795
return SDL_SANDBOX_SNAP;
796
}
797
798
if (access("/run/host/container-manager", F_OK) == 0) {
799
return SDL_SANDBOX_UNKNOWN_CONTAINER;
800
}
801
802
#elif defined(SDL_PLATFORM_MACOS)
803
if (SDL_getenv("APP_SANDBOX_CONTAINER_ID")) {
804
return SDL_SANDBOX_MACOS;
805
}
806
#endif
807
808
return SDL_SANDBOX_NONE;
809
}
810
811
SDL_Sandbox SDL_GetSandbox(void)
812
{
813
static SDL_Sandbox sandbox;
814
static bool sandbox_initialized;
815
816
if (!sandbox_initialized) {
817
sandbox = SDL_DetectSandbox();
818
sandbox_initialized = true;
819
}
820
return sandbox;
821
}
822
823
#ifdef SDL_PLATFORM_WIN32
824
825
#if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
826
// FIXME: Still need to include DllMain() on Watcom C ?
827
828
BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
829
{
830
switch (ul_reason_for_call) {
831
case DLL_PROCESS_ATTACH:
832
case DLL_THREAD_ATTACH:
833
case DLL_THREAD_DETACH:
834
case DLL_PROCESS_DETACH:
835
break;
836
}
837
return TRUE;
838
}
839
#endif // Building DLL
840
841
#endif // defined(SDL_PLATFORM_WIN32)
842
843