SDL_begin_code.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. /* WIKI CATEGORY: BeginCode */
  19. /**
  20. * # CategoryBeginCode
  21. *
  22. * `SDL_begin_code.h` sets things up for C dynamic library function
  23. * definitions, static inlined functions, and structures aligned at 4-byte
  24. * alignment. If you don't like ugly C preprocessor code, don't look at this
  25. * file. :)
  26. *
  27. * SDL's headers use this; applications generally should not include this
  28. * header directly.
  29. */
  30. /* This shouldn't be nested -- included it around code only. */
  31. #ifdef SDL_begin_code_h
  32. #error Nested inclusion of SDL_begin_code.h
  33. #endif
  34. #define SDL_begin_code_h
  35. #ifdef SDL_WIKI_DOCUMENTATION_SECTION
  36. /**
  37. * A macro to tag a symbol as deprecated.
  38. *
  39. * A function is marked deprecated by adding this macro to its declaration:
  40. *
  41. * ```c
  42. * extern SDL_DEPRECATED int ThisFunctionWasABadIdea(void);
  43. * ```
  44. *
  45. * Compilers with deprecation support can give a warning when a deprecated
  46. * function is used. This symbol may be used in SDL's headers, but apps are
  47. * welcome to use it for their own interfaces as well.
  48. *
  49. * SDL, on occasion, might deprecate a function for various reasons. However,
  50. * SDL never removes symbols before major versions, so deprecated interfaces
  51. * in SDL3 will remain available until SDL4, where it would be expected an app
  52. * would have to take steps to migrate anyhow.
  53. *
  54. * On compilers without a deprecation mechanism, this is defined to nothing,
  55. * and using a deprecated function will not generate a warning.
  56. *
  57. * \since This macro is available since SDL 3.2.0.
  58. */
  59. #define SDL_DEPRECATED __attribute__((deprecated))
  60. /**
  61. * A macro to tag a symbol as a public API.
  62. *
  63. * SDL uses this macro for all its public functions. On some targets, it is
  64. * used to signal to the compiler that this function needs to be exported from
  65. * a shared library, but it might have other side effects.
  66. *
  67. * This symbol is used in SDL's headers, but apps and other libraries are
  68. * welcome to use it for their own interfaces as well.
  69. *
  70. * \since This macro is available since SDL 3.2.0.
  71. */
  72. #define SDL_DECLSPEC __attribute__ ((visibility("default")))
  73. /**
  74. * A macro to set a function's calling conventions.
  75. *
  76. * SDL uses this macro for all its public functions, and any callbacks it
  77. * defines. This macro guarantees that calling conventions match between SDL
  78. * and the app, even if the two were built with different compilers or
  79. * optimization settings.
  80. *
  81. * When writing a callback function, it is very important for it to be
  82. * correctly tagged with SDLCALL, as mismatched calling conventions can cause
  83. * strange behaviors and can be difficult to diagnose. Plus, on many
  84. * platforms, SDLCALL is defined to nothing, so compilers won't be able to
  85. * warn that the tag is missing.
  86. *
  87. * This symbol is used in SDL's headers, but apps and other libraries are
  88. * welcome to use it for their own interfaces as well.
  89. *
  90. * \since This macro is available since SDL 3.2.0.
  91. */
  92. #define SDLCALL __cdecl
  93. /**
  94. * A macro to request a function be inlined.
  95. *
  96. * This is a hint to the compiler to inline a function. The compiler is free
  97. * to ignore this request. On compilers without inline support, this is
  98. * defined to nothing.
  99. *
  100. * \since This macro is available since SDL 3.2.0.
  101. */
  102. #define SDL_INLINE __inline
  103. /**
  104. * A macro to demand a function be inlined.
  105. *
  106. * This is a command to the compiler to inline a function. SDL uses this macro
  107. * in its public headers for a handful of simple functions. On compilers
  108. * without forceinline support, this is defined to `static SDL_INLINE`, which
  109. * is often good enough.
  110. *
  111. * This symbol is used in SDL's headers, but apps and other libraries are
  112. * welcome to use it for their own interfaces as well.
  113. *
  114. * \since This macro is available since SDL 3.2.0.
  115. */
  116. #define SDL_FORCE_INLINE __forceinline
  117. /**
  118. * A macro to tag a function as never-returning.
  119. *
  120. * This is a hint to the compiler that a function does not return. An example
  121. * of a function like this is the C runtime's exit() function.
  122. *
  123. * This hint can lead to code optimizations, and help analyzers understand
  124. * code flow better. On compilers without noreturn support, this is defined to
  125. * nothing.
  126. *
  127. * This symbol is used in SDL's headers, but apps and other libraries are
  128. * welcome to use it for their own interfaces as well.
  129. *
  130. * \since This macro is available since SDL 3.2.0.
  131. */
  132. #define SDL_NORETURN __attribute__((noreturn))
  133. /**
  134. * A macro to tag a function as never-returning (for analysis purposes).
  135. *
  136. * This is almost identical to SDL_NORETURN, except functions marked with this
  137. * _can_ actually return. The difference is that this isn't used for code
  138. * generation, but rather static analyzers use this information to assume
  139. * truths about program state and available code paths. Specifically, this tag
  140. * is useful for writing an assertion mechanism. Indeed, SDL_assert uses this
  141. * tag behind the scenes. Generally, apps that don't understand the specific
  142. * use-case for this tag should avoid using it directly.
  143. *
  144. * On compilers without analyzer_noreturn support, this is defined to nothing.
  145. *
  146. * This symbol is used in SDL's headers, but apps and other libraries are
  147. * welcome to use it for their own interfaces as well.
  148. *
  149. * \since This macro is available since SDL 3.2.0.
  150. */
  151. #define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
  152. /**
  153. * A macro to signal that a case statement without a `break` is intentional.
  154. *
  155. * C compilers have gotten more aggressive about warning when a switch's
  156. * `case` block does not end with a `break` or other flow control statement,
  157. * flowing into the next case's code, as this is a common accident that leads
  158. * to strange bugs. But sometimes falling through to the next case is the
  159. * correct and desired behavior. This symbol lets an app communicate this
  160. * intention to the compiler, so it doesn't generate a warning.
  161. *
  162. * It is used like this:
  163. *
  164. * ```c
  165. * switch (x) {
  166. * case 1:
  167. * DoSomethingOnlyForOne();
  168. * SDL_FALLTHROUGH; // tell the compiler this was intentional.
  169. * case 2:
  170. * DoSomethingForOneAndTwo();
  171. * break;
  172. * }
  173. * ```
  174. *
  175. * \since This macro is available since SDL 3.2.0.
  176. */
  177. #define SDL_FALLTHROUGH [[fallthrough]]
  178. /**
  179. * A macro to tag a function's return value as critical.
  180. *
  181. * This is a hint to the compiler that a function's return value should not be
  182. * ignored.
  183. *
  184. * If an NODISCARD function's return value is thrown away (the function is
  185. * called as if it returns `void`), the compiler will issue a warning.
  186. *
  187. * While it's generally good practice to check return values for errors, often
  188. * times legitimate programs do not for good reasons. Be careful about what
  189. * functions are tagged as NODISCARD. It operates best when used on a function
  190. * that's failure is surprising and catastrophic; a good example would be a
  191. * program that checks the return values of all its file write function calls
  192. * but not the call to close the file, which it assumes incorrectly never
  193. * fails.
  194. *
  195. * Function callers that want to throw away a NODISCARD return value can call
  196. * the function with a `(void)` cast, which informs the compiler the act is
  197. * intentional.
  198. *
  199. * On compilers without nodiscard support, this is defined to nothing.
  200. *
  201. * \since This macro is available since SDL 3.2.0.
  202. */
  203. #define SDL_NODISCARD [[nodiscard]]
  204. /**
  205. * A macro to tag a function as an allocator.
  206. *
  207. * This is a hint to the compiler that a function is an allocator, like
  208. * malloc(), with certain rules. A description of how GCC treats this hint is
  209. * here:
  210. *
  211. * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
  212. *
  213. * On compilers without allocator tag support, this is defined to nothing.
  214. *
  215. * Most apps don't need to, and should not, use this directly.
  216. *
  217. * \since This macro is available since SDL 3.2.0.
  218. */
  219. #define SDL_MALLOC __declspec(allocator) __desclspec(restrict)
  220. /**
  221. * A macro to tag a function as returning a certain allocation.
  222. *
  223. * This is a hint to the compiler that a function allocates and returns a
  224. * specific amount of memory based on one of its arguments. For example, the C
  225. * runtime's malloc() function could use this macro with an argument of 1
  226. * (first argument to malloc is the size of the allocation).
  227. *
  228. * On compilers without alloc_size support, this is defined to nothing.
  229. *
  230. * Most apps don't need to, and should not, use this directly.
  231. *
  232. * \since This macro is available since SDL 3.2.0.
  233. */
  234. #define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p)))
  235. /**
  236. * A macro to tag a pointer variable, to help with pointer aliasing.
  237. *
  238. * A good explanation of the restrict keyword is here:
  239. *
  240. * https://en.wikipedia.org/wiki/Restrict
  241. *
  242. * On compilers without restrict support, this is defined to nothing.
  243. *
  244. * \since This macro is available since SDL 3.4.0.
  245. */
  246. #define SDL_RESTRICT __restrict
  247. /**
  248. * Check if the compiler supports a given builtin functionality.
  249. *
  250. * This allows preprocessor checks for things that otherwise might fail to
  251. * compile.
  252. *
  253. * Supported by virtually all clang versions and more-recent GCCs. Use this
  254. * instead of checking the clang version if possible.
  255. *
  256. * On compilers without has_builtin support, this is defined to 0 (always
  257. * false).
  258. *
  259. * \since This macro is available since SDL 3.2.0.
  260. */
  261. #define SDL_HAS_BUILTIN(x) __has_builtin(x)
  262. /**
  263. * A macro to specify data alignment.
  264. *
  265. * This informs the compiler that a given datatype or variable must be aligned
  266. * to a specific byte count.
  267. *
  268. * For example:
  269. *
  270. * ```c
  271. * // make sure this is struct is aligned to 16 bytes for SIMD access.
  272. * typedef struct {
  273. * float x, y, z, w;
  274. * } SDL_ALIGNED(16) MySIMDAlignedData;
  275. *
  276. * // make sure this one field in a struct is aligned to 16 bytes for SIMD access.
  277. * typedef struct {
  278. * SomeStuff stuff;
  279. * float position[4] SDL_ALIGNED(16);
  280. * SomeOtherStuff other_stuff;
  281. * } MyStruct;
  282. *
  283. * // make sure this variable is aligned to 32 bytes.
  284. * int SDL_ALIGNED(32) myval = 0;
  285. * ```
  286. *
  287. * Alignment is only guaranteed for things the compiler places: local
  288. * variables on the stack and global/static variables. To dynamically allocate
  289. * something that respects this alignment, use SDL_aligned_alloc() or some
  290. * other mechanism.
  291. *
  292. * On compilers without alignment support, this macro is defined to an invalid
  293. * symbol, to make it clear that the current compiler is likely to generate
  294. * incorrect code when it sees this macro.
  295. *
  296. * \param x the byte count to align to, so the data's address will be a
  297. * multiple of this value.
  298. *
  299. * \since This macro is available since SDL 3.4.0.
  300. */
  301. #define SDL_ALIGNED(x) __attribute__((aligned(x)))
  302. /* end of wiki documentation section. */
  303. #endif
  304. /* `restrict` is from C99, but __restrict works with both Visual Studio and GCC. */
  305. #ifndef SDL_RESTRICT
  306. # if defined(restrict) || ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)))
  307. # defined SDL_RESTRICT restrict
  308. # elif defined(_MSC_VER) || defined(__GNUC__) || defined(__clang__)
  309. # define SDL_RESTRICT __restrict
  310. # else
  311. # define SDL_RESTRICT
  312. # endif
  313. #endif
  314. #ifndef SDL_HAS_BUILTIN
  315. #ifdef __has_builtin
  316. #define SDL_HAS_BUILTIN(x) __has_builtin(x)
  317. #else
  318. #define SDL_HAS_BUILTIN(x) 0
  319. #endif
  320. #endif
  321. #ifndef SDL_DEPRECATED
  322. # if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */
  323. # define SDL_DEPRECATED __attribute__((deprecated))
  324. # elif defined(_MSC_VER)
  325. # define SDL_DEPRECATED __declspec(deprecated)
  326. # else
  327. # define SDL_DEPRECATED
  328. # endif
  329. #endif
  330. #ifndef SDL_UNUSED
  331. # ifdef __GNUC__
  332. # define SDL_UNUSED __attribute__((unused))
  333. # else
  334. # define SDL_UNUSED
  335. # endif
  336. #endif
  337. /* Some compilers use a special export keyword */
  338. #ifndef SDL_DECLSPEC
  339. # if defined(SDL_PLATFORM_WINDOWS)
  340. # ifdef DLL_EXPORT
  341. # define SDL_DECLSPEC __declspec(dllexport)
  342. # else
  343. # define SDL_DECLSPEC
  344. # endif
  345. # else
  346. # if defined(__GNUC__) && __GNUC__ >= 4
  347. # define SDL_DECLSPEC __attribute__ ((visibility("default")))
  348. # else
  349. # define SDL_DECLSPEC
  350. # endif
  351. # endif
  352. #endif
  353. /* By default SDL uses the C calling convention */
  354. #ifndef SDLCALL
  355. #if defined(SDL_PLATFORM_WINDOWS) && !defined(__GNUC__)
  356. #define SDLCALL __cdecl
  357. #else
  358. #define SDLCALL
  359. #endif
  360. #endif /* SDLCALL */
  361. /* Force structure packing at 4 byte alignment.
  362. This is necessary if the header is included in code which has structure
  363. packing set to an alternate value, say for loading structures from disk.
  364. The packing is reset to the previous value in SDL_close_code.h
  365. */
  366. #if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
  367. #ifdef _MSC_VER
  368. #pragma warning(disable: 4103)
  369. #endif
  370. #ifdef __clang__
  371. #pragma clang diagnostic ignored "-Wpragma-pack"
  372. #endif
  373. #ifdef __BORLANDC__
  374. #pragma nopackwarning
  375. #endif
  376. #ifdef _WIN64
  377. /* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
  378. #pragma pack(push,8)
  379. #else
  380. #pragma pack(push,4)
  381. #endif
  382. #endif /* Compiler needs structure packing set */
  383. #ifndef SDL_INLINE
  384. #ifdef __GNUC__
  385. #define SDL_INLINE __inline__
  386. #elif defined(_MSC_VER) || defined(__BORLANDC__) || \
  387. defined(__DMC__) || defined(__SC__) || \
  388. defined(__WATCOMC__) || defined(__LCC__) || \
  389. defined(__DECC) || defined(__CC_ARM)
  390. #define SDL_INLINE __inline
  391. #ifndef __inline__
  392. #define __inline__ __inline
  393. #endif
  394. #else
  395. #define SDL_INLINE inline
  396. #ifndef __inline__
  397. #define __inline__ inline
  398. #endif
  399. #endif
  400. #endif /* SDL_INLINE not defined */
  401. #ifndef SDL_FORCE_INLINE
  402. #ifdef _MSC_VER
  403. #define SDL_FORCE_INLINE __forceinline
  404. #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
  405. #define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__
  406. #else
  407. #define SDL_FORCE_INLINE static SDL_INLINE
  408. #endif
  409. #endif /* SDL_FORCE_INLINE not defined */
  410. #ifndef SDL_NORETURN
  411. #if defined(__GNUC__)
  412. #define SDL_NORETURN __attribute__((noreturn))
  413. #elif defined(_MSC_VER)
  414. #define SDL_NORETURN __declspec(noreturn)
  415. #else
  416. #define SDL_NORETURN
  417. #endif
  418. #endif /* SDL_NORETURN not defined */
  419. #ifdef __clang__
  420. #if __has_feature(attribute_analyzer_noreturn)
  421. #define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
  422. #endif
  423. #endif
  424. #ifndef SDL_ANALYZER_NORETURN
  425. #define SDL_ANALYZER_NORETURN
  426. #endif
  427. /* Apparently this is needed by several Windows compilers */
  428. #ifndef __MACH__
  429. #ifndef NULL
  430. #ifdef __cplusplus
  431. #define NULL 0
  432. #else
  433. #define NULL ((void *)0)
  434. #endif
  435. #endif /* NULL */
  436. #endif /* ! macOS - breaks precompiled headers */
  437. #ifndef SDL_FALLTHROUGH
  438. #if (defined(__cplusplus) && __cplusplus >= 201703L) || \
  439. (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L)
  440. #define SDL_FALLTHROUGH [[fallthrough]]
  441. #else
  442. #if defined(__has_attribute) && !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
  443. #define SDL_HAS_FALLTHROUGH __has_attribute(__fallthrough__)
  444. #else
  445. #define SDL_HAS_FALLTHROUGH 0
  446. #endif /* __has_attribute */
  447. #if SDL_HAS_FALLTHROUGH && \
  448. ((defined(__GNUC__) && __GNUC__ >= 7) || \
  449. (defined(__clang_major__) && __clang_major__ >= 10))
  450. #define SDL_FALLTHROUGH __attribute__((__fallthrough__))
  451. #else
  452. #define SDL_FALLTHROUGH do {} while (0) /* fallthrough */
  453. #endif /* SDL_HAS_FALLTHROUGH */
  454. #undef SDL_HAS_FALLTHROUGH
  455. #endif /* C++17 or C2x */
  456. #endif /* SDL_FALLTHROUGH not defined */
  457. #ifndef SDL_NODISCARD
  458. #if (defined(__cplusplus) && __cplusplus >= 201703L) || \
  459. (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
  460. #define SDL_NODISCARD [[nodiscard]]
  461. #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
  462. #define SDL_NODISCARD __attribute__((warn_unused_result))
  463. #elif defined(_MSC_VER) && (_MSC_VER >= 1700)
  464. #define SDL_NODISCARD _Check_return_
  465. #else
  466. #define SDL_NODISCARD
  467. #endif /* C++17 or C23 */
  468. #endif /* SDL_NODISCARD not defined */
  469. #ifndef SDL_MALLOC
  470. #if defined(__GNUC__) && (__GNUC__ >= 3)
  471. #define SDL_MALLOC __attribute__((malloc))
  472. /** FIXME
  473. #elif defined(_MSC_VER)
  474. #define SDL_MALLOC __declspec(allocator) __desclspec(restrict)
  475. **/
  476. #else
  477. #define SDL_MALLOC
  478. #endif
  479. #endif /* SDL_MALLOC not defined */
  480. #ifndef SDL_ALLOC_SIZE
  481. #if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
  482. #define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p)))
  483. #elif defined(_MSC_VER)
  484. #define SDL_ALLOC_SIZE(p)
  485. #else
  486. #define SDL_ALLOC_SIZE(p)
  487. #endif
  488. #endif /* SDL_ALLOC_SIZE not defined */
  489. #ifndef SDL_ALLOC_SIZE2
  490. #if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
  491. #define SDL_ALLOC_SIZE2(p1, p2) __attribute__((alloc_size(p1, p2)))
  492. #elif defined(_MSC_VER)
  493. #define SDL_ALLOC_SIZE2(p1, p2)
  494. #else
  495. #define SDL_ALLOC_SIZE2(p1, p2)
  496. #endif
  497. #endif /* SDL_ALLOC_SIZE2 not defined */
  498. #ifndef SDL_ALIGNED
  499. #if defined(__clang__) || defined(__GNUC__)
  500. #define SDL_ALIGNED(x) __attribute__((aligned(x)))
  501. #elif defined(_MSC_VER)
  502. #define SDL_ALIGNED(x) __declspec(align(x))
  503. #elif defined(__cplusplus) && (__cplusplus >= 201103L)
  504. #define SDL_ALIGNED(x) alignas(x)
  505. #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
  506. #define SDL_ALIGNED(x) _Alignas(x)
  507. #else
  508. #define SDL_ALIGNED(x) PLEASE_DEFINE_SDL_ALIGNED
  509. #endif
  510. #endif /* SDL_ALIGNED not defined */