21
#include "SDL_internal.h"
22
#include "SDL3/SDL_revision.h"
24
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)
25
#include "core/windows/SDL_windows.h"
26
#elif !defined(SDL_PLATFORM_WINRT)
31
#include "core/linux/SDL_dbus.h"
33
#ifdef SDL_PLATFORM_EMSCRIPTEN
34
#include <emscripten.h>
39
#include "SDL_assert_c.h"
40
#include "SDL_hints_c.h"
42
#include "SDL_properties_c.h"
43
#include "audio/SDL_sysaudio.h"
44
#include "camera/SDL_camera_c.h"
45
#include "cpuinfo/SDL_cpuinfo_c.h"
46
#include "events/SDL_events_c.h"
47
#include "haptic/SDL_haptic_c.h"
48
#include "joystick/SDL_gamepad_c.h"
49
#include "joystick/SDL_joystick_c.h"
50
#include "render/SDL_sysrender.h"
51
#include "sensor/SDL_sensor_c.h"
52
#include "thread/SDL_thread_c.h"
53
#include "video/SDL_pixels_c.h"
54
#include "video/SDL_video_c.h"
55
#include "filesystem/SDL_filesystem_c.h"
57
#define SDL_INIT_EVERYTHING ~0U
60
#include "timer/SDL_timer_c.h"
61
#ifdef SDL_VIDEO_DRIVER_WINDOWS
62
extern bool SDL_HelperWindowCreate(void);
63
extern void SDL_HelperWindowDestroy(void);
66
#ifdef SDL_BUILD_MAJOR_VERSION
67
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MAJOR_VERSION,
68
SDL_MAJOR_VERSION == SDL_BUILD_MAJOR_VERSION);
69
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MINOR_VERSION,
70
SDL_MINOR_VERSION == SDL_BUILD_MINOR_VERSION);
71
SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MICRO_VERSION,
72
SDL_MICRO_VERSION == SDL_BUILD_MICRO_VERSION);
76
SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_min, SDL_MAJOR_VERSION >= 0);
77
SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_max, SDL_MAJOR_VERSION <= 10);
78
SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_min, SDL_MINOR_VERSION >= 0);
79
SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_max, SDL_MINOR_VERSION <= 999);
80
SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_min, SDL_MICRO_VERSION >= 0);
81
SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_max, SDL_MICRO_VERSION <= 999);
86
extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
87
SDL_NORETURN void SDL_ExitProcess(int exitcode)
89
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)
93
TerminateProcess(GetCurrentProcess(), exitcode);
96
ExitProcess(exitcode);
97
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
98
emscripten_cancel_main_loop();
99
emscripten_force_exit(exitcode);
101
#elif defined(SDL_PLATFORM_HAIKU)
103
#elif defined(HAVE__EXIT)
112
SDL_bool SDL_SetAppMetadata(const char *appname, const char *appversion, const char *appidentifier)
114
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, appname);
115
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, appversion);
116
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, appidentifier);
120
static bool SDL_ValidMetadataProperty(const char *name)
122
if (!name || !*name) {
126
if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0 ||
127
SDL_strcmp(name, SDL_PROP_APP_METADATA_VERSION_STRING) == 0 ||
128
SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0 ||
129
SDL_strcmp(name, SDL_PROP_APP_METADATA_CREATOR_STRING) == 0 ||
130
SDL_strcmp(name, SDL_PROP_APP_METADATA_COPYRIGHT_STRING) == 0 ||
131
SDL_strcmp(name, SDL_PROP_APP_METADATA_URL_STRING) == 0 ||
132
SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) {
138
SDL_bool SDL_SetAppMetadataProperty(const char *name, const char *value)
140
if (!SDL_ValidMetadataProperty(name)) {
141
return SDL_InvalidParamError("name");
144
return SDL_SetStringProperty(SDL_GetGlobalProperties(), name, value);
147
const char *SDL_GetAppMetadataProperty(const char *name)
149
if (!SDL_ValidMetadataProperty(name)) {
150
SDL_InvalidParamError("name");
154
const char *value = NULL;
155
if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) {
156
value = SDL_GetHint(SDL_HINT_APP_NAME);
157
} else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0) {
158
value = SDL_GetHint(SDL_HINT_APP_ID);
160
if (!value || !*value) {
161
value = SDL_GetStringProperty(SDL_GetGlobalProperties(), name, NULL);
163
if (!value || !*value) {
164
if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) {
165
value = "SDL Application";
166
} else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) {
167
value = "application";
175
#ifdef SDL_MAIN_NEEDED
176
static bool SDL_MainIsReady = false;
178
static bool SDL_MainIsReady = true;
180
static bool SDL_bInMainQuit = false;
181
static Uint8 SDL_SubsystemRefCount[32];
184
static void SDL_IncrementSubsystemRefCount(Uint32 subsystem)
186
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
187
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
188
if (subsystem_index >= 0) {
189
++SDL_SubsystemRefCount[subsystem_index];
194
static void SDL_DecrementSubsystemRefCount(Uint32 subsystem)
196
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
197
if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] > 0)) {
198
if (SDL_bInMainQuit) {
199
SDL_SubsystemRefCount[subsystem_index] = 0;
201
--SDL_SubsystemRefCount[subsystem_index];
207
static bool SDL_ShouldInitSubsystem(Uint32 subsystem)
209
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
210
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
211
return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0));
215
static bool SDL_ShouldQuitSubsystem(Uint32 subsystem)
217
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
218
if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) {
225
return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit);
230
static bool SDL_InitOrIncrementSubsystem(Uint32 subsystem)
232
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
233
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
234
if (subsystem_index < 0) {
237
if (SDL_SubsystemRefCount[subsystem_index] > 0) {
238
++SDL_SubsystemRefCount[subsystem_index];
241
return SDL_InitSubSystem(subsystem);
244
void SDL_SetMainReady(void)
246
SDL_MainIsReady = true;
250
void SDL_InitMainThread(void)
254
SDL_InitFilesystem();
256
SDL_InitProperties();
257
SDL_GetGlobalProperties();
261
static void SDL_QuitMainThread(void)
264
SDL_QuitProperties();
266
SDL_QuitFilesystem();
271
SDL_bool SDL_InitSubSystem(SDL_InitFlags flags)
273
Uint32 flags_initialized = 0;
275
if (!SDL_MainIsReady) {
276
return SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
279
SDL_InitMainThread();
281
#ifdef SDL_USE_LIBDBUS
285
#ifdef SDL_VIDEO_DRIVER_WINDOWS
286
if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) {
287
if (!SDL_HelperWindowCreate()) {
294
if (flags & SDL_INIT_EVENTS) {
295
if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) {
296
SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS);
297
if (!SDL_InitEvents()) {
298
SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS);
302
SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS);
304
flags_initialized |= SDL_INIT_EVENTS;
308
if (flags & SDL_INIT_TIMER) {
309
if (SDL_ShouldInitSubsystem(SDL_INIT_TIMER)) {
310
SDL_IncrementSubsystemRefCount(SDL_INIT_TIMER);
311
if (!SDL_InitTimers()) {
312
SDL_DecrementSubsystemRefCount(SDL_INIT_TIMER);
316
SDL_IncrementSubsystemRefCount(SDL_INIT_TIMER);
318
flags_initialized |= SDL_INIT_TIMER;
322
if (flags & SDL_INIT_VIDEO) {
323
#ifndef SDL_VIDEO_DISABLED
324
if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) {
326
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
330
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
331
if (!SDL_VideoInit(NULL)) {
332
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
336
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
338
flags_initialized |= SDL_INIT_VIDEO;
340
SDL_SetError("SDL not built with video support");
346
if (flags & SDL_INIT_AUDIO) {
347
#ifndef SDL_AUDIO_DISABLED
348
if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) {
350
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
354
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
355
if (!SDL_InitAudio(NULL)) {
356
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
360
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
362
flags_initialized |= SDL_INIT_AUDIO;
364
SDL_SetError("SDL not built with audio support");
370
if (flags & SDL_INIT_JOYSTICK) {
371
#ifndef SDL_JOYSTICK_DISABLED
372
if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
374
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
378
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
379
if (!SDL_InitJoysticks()) {
380
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
384
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
386
flags_initialized |= SDL_INIT_JOYSTICK;
388
SDL_SetError("SDL not built with joystick support");
393
if (flags & SDL_INIT_GAMEPAD) {
394
#ifndef SDL_JOYSTICK_DISABLED
395
if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) {
397
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) {
401
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
402
if (!SDL_InitGamepads()) {
403
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
407
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
409
flags_initialized |= SDL_INIT_GAMEPAD;
411
SDL_SetError("SDL not built with joystick support");
417
if (flags & SDL_INIT_HAPTIC) {
418
#ifndef SDL_HAPTIC_DISABLED
419
if (SDL_ShouldInitSubsystem(SDL_INIT_HAPTIC)) {
420
SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC);
421
if (!SDL_InitHaptics()) {
422
SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC);
426
SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC);
428
flags_initialized |= SDL_INIT_HAPTIC;
430
SDL_SetError("SDL not built with haptic (force feedback) support");
436
if (flags & SDL_INIT_SENSOR) {
437
#ifndef SDL_SENSOR_DISABLED
438
if (SDL_ShouldInitSubsystem(SDL_INIT_SENSOR)) {
439
SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR);
440
if (!SDL_InitSensors()) {
441
SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR);
445
SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR);
447
flags_initialized |= SDL_INIT_SENSOR;
449
SDL_SetError("SDL not built with sensor support");
455
if (flags & SDL_INIT_CAMERA) {
456
#ifndef SDL_CAMERA_DISABLED
457
if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) {
459
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
463
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
464
if (!SDL_CameraInit(NULL)) {
465
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
469
SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA);
471
flags_initialized |= SDL_INIT_CAMERA;
473
SDL_SetError("SDL not built with camera support");
478
(void)flags_initialized;
480
return SDL_ClearError();
483
SDL_QuitSubSystem(flags_initialized);
487
SDL_bool SDL_Init(SDL_InitFlags flags)
489
return SDL_InitSubSystem(flags);
492
void SDL_QuitSubSystem(SDL_InitFlags flags)
496
#ifndef SDL_CAMERA_DISABLED
497
if (flags & SDL_INIT_CAMERA) {
498
if (SDL_ShouldQuitSubsystem(SDL_INIT_CAMERA)) {
501
SDL_QuitSubSystem(SDL_INIT_EVENTS);
503
SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA);
507
#ifndef SDL_SENSOR_DISABLED
508
if (flags & SDL_INIT_SENSOR) {
509
if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) {
512
SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR);
516
#ifndef SDL_JOYSTICK_DISABLED
517
if (flags & SDL_INIT_GAMEPAD) {
518
if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) {
521
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
523
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
526
if (flags & SDL_INIT_JOYSTICK) {
527
if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
530
SDL_QuitSubSystem(SDL_INIT_EVENTS);
532
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
536
#ifndef SDL_HAPTIC_DISABLED
537
if (flags & SDL_INIT_HAPTIC) {
538
if (SDL_ShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
541
SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC);
545
#ifndef SDL_AUDIO_DISABLED
546
if (flags & SDL_INIT_AUDIO) {
547
if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) {
550
SDL_QuitSubSystem(SDL_INIT_EVENTS);
552
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
556
#ifndef SDL_VIDEO_DISABLED
557
if (flags & SDL_INIT_VIDEO) {
558
if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) {
562
SDL_QuitSubSystem(SDL_INIT_EVENTS);
564
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
568
if (flags & SDL_INIT_TIMER) {
569
if (SDL_ShouldQuitSubsystem(SDL_INIT_TIMER)) {
572
SDL_DecrementSubsystemRefCount(SDL_INIT_TIMER);
575
if (flags & SDL_INIT_EVENTS) {
576
if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) {
579
SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS);
583
Uint32 SDL_WasInit(SDL_InitFlags flags)
586
int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
587
Uint32 initialized = 0;
590
if (SDL_HasExactlyOneBitSet32(flags)) {
591
int subsystem_index = SDL_MostSignificantBitIndex32(flags);
592
return SDL_SubsystemRefCount[subsystem_index] ? flags : 0;
596
flags = SDL_INIT_EVERYTHING;
599
num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
602
for (i = 0; i < num_subsystems; ++i) {
603
if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
604
initialized |= (1 << i);
615
SDL_bInMainQuit = true;
618
#ifdef SDL_VIDEO_DRIVER_WINDOWS
619
SDL_HelperWindowDestroy();
621
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
623
#ifdef SDL_USE_LIBDBUS
627
SDL_SetObjectsInvalid();
628
SDL_AssertionsQuit();
630
SDL_QuitPixelFormatDetails();
637
SDL_memset(SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount));
639
SDL_QuitMainThread();
641
SDL_bInMainQuit = false;
645
int SDL_GetVersion(void)
651
const char *SDL_GetRevision(void)
657
const char *SDL_GetPlatform(void)
659
#if defined(SDL_PLATFORM_AIX)
661
#elif defined(SDL_PLATFORM_ANDROID)
663
#elif defined(SDL_PLATFORM_BSDI)
665
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
667
#elif defined(SDL_PLATFORM_FREEBSD)
669
#elif defined(SDL_PLATFORM_HAIKU)
671
#elif defined(SDL_PLATFORM_HPUX)
673
#elif defined(SDL_PLATFORM_IRIX)
675
#elif defined(SDL_PLATFORM_LINUX)
677
#elif defined(__MINT__)
679
#elif defined(SDL_PLATFORM_MACOS)
681
#elif defined(SDL_PLATFORM_NETBSD)
683
#elif defined(SDL_PLATFORM_OPENBSD)
685
#elif defined(SDL_PLATFORM_OS2)
687
#elif defined(SDL_PLATFORM_OSF)
689
#elif defined(SDL_PLATFORM_QNXNTO)
690
return "QNX Neutrino";
691
#elif defined(SDL_PLATFORM_RISCOS)
693
#elif defined(SDL_PLATFORM_SOLARIS)
695
#elif defined(SDL_PLATFORM_WIN32)
697
#elif defined(SDL_PLATFORM_WINRT)
699
#elif defined(SDL_PLATFORM_WINGDK)
701
#elif defined(SDL_PLATFORM_XBOXONE)
703
#elif defined(SDL_PLATFORM_XBOXSERIES)
704
return "Xbox Series X|S";
705
#elif defined(SDL_PLATFORM_IOS)
707
#elif defined(SDL_PLATFORM_TVOS)
709
#elif defined(SDL_PLATFORM_PS2)
710
return "PlayStation 2";
711
#elif defined(SDL_PLATFORM_PSP)
712
return "PlayStation Portable";
713
#elif defined(SDL_PLATFORM_VITA)
714
return "PlayStation Vita";
715
#elif defined(SDL_PLATFORM_NGAGE)
716
return "Nokia N-Gage";
717
#elif defined(SDL_PLATFORM_3DS)
718
return "Nintendo 3DS";
719
#elif defined(__managarm__)
722
return "Unknown (see SDL_platform.h)";
726
SDL_bool SDL_IsTablet(void)
728
#ifdef SDL_PLATFORM_ANDROID
729
extern bool SDL_IsAndroidTablet(void);
730
return SDL_IsAndroidTablet();
731
#elif defined(SDL_PLATFORM_IOS)
732
extern bool SDL_IsIPad(void);
739
#ifdef SDL_PLATFORM_WIN32
741
#if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
744
BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
746
switch (ul_reason_for_call) {
747
case DLL_PROCESS_ATTACH:
748
case DLL_THREAD_ATTACH:
749
case DLL_THREAD_DETACH:
750
case DLL_PROCESS_DETACH: