mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-21 16:21:06 +01:00
Compare commits
394 Commits
preview-3.
...
prerelease
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f173fd28f0 | ||
|
|
eba0630907 | ||
|
|
1978506112 | ||
|
|
eea8090f84 | ||
|
|
96b5c92780 | ||
|
|
b74ba6298c | ||
|
|
9369a341c6 | ||
|
|
2c11d62d17 | ||
|
|
6602f12744 | ||
|
|
ab67be7e5a | ||
|
|
3d2b79c096 | ||
|
|
e047aeeb7c | ||
|
|
f38d31a811 | ||
|
|
71147216dc | ||
|
|
3659b2f100 | ||
|
|
ade2720829 | ||
|
|
69c78a7989 | ||
|
|
a5aa67882d | ||
|
|
37715c4029 | ||
|
|
82593fd6c1 | ||
|
|
0f37491a8b | ||
|
|
f5ea8805e1 | ||
|
|
a3992f504c | ||
|
|
27744952d1 | ||
|
|
0e96cbd8ce | ||
|
|
5c7d549267 | ||
|
|
e41bdfafe4 | ||
|
|
fc8d725367 | ||
|
|
03c932b9a7 | ||
|
|
09304831f6 | ||
|
|
8be18741e1 | ||
|
|
8e644111c2 | ||
|
|
c7133a6720 | ||
|
|
12e3162c5f | ||
|
|
2cb9a4fcc1 | ||
|
|
bc17a8922b | ||
|
|
ccdc9231f5 | ||
|
|
7b74fbb73f | ||
|
|
b5dd0ee07b | ||
|
|
3b12019892 | ||
|
|
c61497b744 | ||
|
|
d83fa92d58 | ||
|
|
aae2f74ae6 | ||
|
|
70c2f576c8 | ||
|
|
f97e53509e | ||
|
|
36b85ce909 | ||
|
|
5ae68e9a0f | ||
|
|
0c5ad99ec1 | ||
|
|
65ef4df6d4 | ||
|
|
cc681ffeda | ||
|
|
3313cb9c4b | ||
|
|
1dea7c801b | ||
|
|
adb0013470 | ||
|
|
bffc4ccc50 | ||
|
|
505cd6cd22 | ||
|
|
866ec367ad | ||
|
|
f92435cdb9 | ||
|
|
1961b16b78 | ||
|
|
dedab7b72c | ||
|
|
6217672bde | ||
|
|
e1edeab0c9 | ||
|
|
22decf4783 | ||
|
|
737be31c63 | ||
|
|
6d99204a82 | ||
|
|
2b1904a849 | ||
|
|
c1db2b4bb0 | ||
|
|
29213efa65 | ||
|
|
b7c8b2f29a | ||
|
|
ea1514ab63 | ||
|
|
955698c635 | ||
|
|
1c46c8a3dc | ||
|
|
778f70c906 | ||
|
|
9c6c2387b9 | ||
|
|
5e9163592f | ||
|
|
b9d794bb37 | ||
|
|
7af479bc53 | ||
|
|
defd7895da | ||
|
|
625d090243 | ||
|
|
fdcd548612 | ||
|
|
54b15532d3 | ||
|
|
eda8d1d842 | ||
|
|
21f93e127b | ||
|
|
1edb850639 | ||
|
|
52a4366e54 | ||
|
|
7e5f3330ff | ||
|
|
9b348ef6e8 | ||
|
|
da863ff5f9 | ||
|
|
29f3844b01 | ||
|
|
74653b3cd5 | ||
|
|
24fe3c48a0 | ||
|
|
55a566a6b4 | ||
|
|
e221905195 | ||
|
|
9896dc18e7 | ||
|
|
8fa93d64ab | ||
|
|
56269cd010 | ||
|
|
4e79d2ad64 | ||
|
|
6534345d9a | ||
|
|
7f0d0d0046 | ||
|
|
f7ded3db5e | ||
|
|
ebd3aa5289 | ||
|
|
ba919832e4 | ||
|
|
1fdc7975cb | ||
|
|
15f98b2a61 | ||
|
|
17ab859907 | ||
|
|
ff44bad9bd | ||
|
|
54ef731534 | ||
|
|
a37d3f96f4 | ||
|
|
ce5e46c37d | ||
|
|
7d5ec38953 | ||
|
|
c0a2ae2a4a | ||
|
|
7388054fa2 | ||
|
|
d0e70c37ab | ||
|
|
f0d958d850 | ||
|
|
6a1218c1cc | ||
|
|
1fc093491a | ||
|
|
fed80a0d41 | ||
|
|
b984846dd0 | ||
|
|
67728a5450 | ||
|
|
4b0514f087 | ||
|
|
029746a3d4 | ||
|
|
62a7ac507a | ||
|
|
faf1e770dd | ||
|
|
22df7c66ed | ||
|
|
d9230f4796 | ||
|
|
0f76744828 | ||
|
|
3dee60d65f | ||
|
|
06583ce421 | ||
|
|
99d7dad7e6 | ||
|
|
0cc3354731 | ||
|
|
be15de6baa | ||
|
|
082848e945 | ||
|
|
36976ecb43 | ||
|
|
92eaa34277 | ||
|
|
a7ab3a604b | ||
|
|
168e4eb532 | ||
|
|
a9a24ac000 | ||
|
|
4a769b6475 | ||
|
|
61bf7087f5 | ||
|
|
9f444b3981 | ||
|
|
2ef005afe5 | ||
|
|
d50cda3247 | ||
|
|
fa3467a94d | ||
|
|
ef0ae4c903 | ||
|
|
6d60cc65cf | ||
|
|
0c5655940c | ||
|
|
1209abf9dc | ||
|
|
a1ade13f1e | ||
|
|
1e5cbbc1d0 | ||
|
|
168f78b8b7 | ||
|
|
cc768f3e88 | ||
|
|
908216bbae | ||
|
|
47360a9a46 | ||
|
|
64bf432beb | ||
|
|
8f21fe4994 | ||
|
|
44471b3ea4 | ||
|
|
4931c675ab | ||
|
|
b144c79da2 | ||
|
|
8920736df0 | ||
|
|
17a891daa8 | ||
|
|
3ba9bdfc01 | ||
|
|
14470755b7 | ||
|
|
d058781f71 | ||
|
|
c68254927f | ||
|
|
a882afafe5 | ||
|
|
f1145186ea | ||
|
|
770b38b4f1 | ||
|
|
3f0545587f | ||
|
|
667272e71d | ||
|
|
d9d0df2534 | ||
|
|
abf7a8974b | ||
|
|
4bc9ab665d | ||
|
|
07f995eb72 | ||
|
|
3ae7a54c94 | ||
|
|
b83bd80424 | ||
|
|
10f6b860ee | ||
|
|
d4bef0d5ba | ||
|
|
005cb20e67 | ||
|
|
c6935f9dcb | ||
|
|
a4c269cd10 | ||
|
|
0f763da015 | ||
|
|
cb6272ed2d | ||
|
|
dccf486a0a | ||
|
|
d62f141b29 | ||
|
|
0ae3d7b0b0 | ||
|
|
ed6d41f55b | ||
|
|
cc3b5766fa | ||
|
|
2b2bf85970 | ||
|
|
367c8d7c7b | ||
|
|
919254cdd1 | ||
|
|
879f081de3 | ||
|
|
9fd3dbfc42 | ||
|
|
f0d4aca03d | ||
|
|
ae6cdea0fa | ||
|
|
d66946cee7 | ||
|
|
7db0e48454 | ||
|
|
a01d6f109d | ||
|
|
4cc9153df2 | ||
|
|
e2e8f86076 | ||
|
|
493bc621e4 | ||
|
|
dafca86123 | ||
|
|
54f129f765 | ||
|
|
9dbde4542c | ||
|
|
702a1adf4a | ||
|
|
667720d5af | ||
|
|
d0926d380e | ||
|
|
379c47cc75 | ||
|
|
2079517802 | ||
|
|
0c5f7f6a33 | ||
|
|
e1af623631 | ||
|
|
1998b65045 | ||
|
|
04a62cba1f | ||
|
|
3dab15d3b4 | ||
|
|
65989d269e | ||
|
|
b2585ac236 | ||
|
|
536507101d | ||
|
|
b7ea19d5e5 | ||
|
|
ac0f77b7e6 | ||
|
|
6905714986 | ||
|
|
25ab8c99df | ||
|
|
7073cfc58e | ||
|
|
5bed8ec603 | ||
|
|
a63e848509 | ||
|
|
5ec6147acb | ||
|
|
6b07e13fef | ||
|
|
fffaf122df | ||
|
|
dde7fa3b17 | ||
|
|
6baaa0fe87 | ||
|
|
6a7fb838f4 | ||
|
|
eccd5c03c3 | ||
|
|
33c70af2f8 | ||
|
|
1c77304ee9 | ||
|
|
ff890d1733 | ||
|
|
6389f4db4c | ||
|
|
ead02b08dd | ||
|
|
4e5ba722fd | ||
|
|
d29f368ca8 | ||
|
|
3399bc600e | ||
|
|
97ebfbf7a0 | ||
|
|
d9be8b9a00 | ||
|
|
01a812cbca | ||
|
|
b5624e14ff | ||
|
|
0b2073d143 | ||
|
|
1b79ba9ab6 | ||
|
|
6976b57988 | ||
|
|
799c6aa629 | ||
|
|
0cc2b026e7 | ||
|
|
f3d39815e7 | ||
|
|
f6a05121ec | ||
|
|
5d0236ad51 | ||
|
|
2382d3831c | ||
|
|
a96664674f | ||
|
|
836dad75ae | ||
|
|
53ee410d7a | ||
|
|
2bc886d0bd | ||
|
|
2be18f340f | ||
|
|
b9c790949e | ||
|
|
2f41dd7b5c | ||
|
|
704ac98d3f | ||
|
|
089dc86bcf | ||
|
|
cc2a272d6f | ||
|
|
ac0edbe9d2 | ||
|
|
2b365983db | ||
|
|
78152d13ee | ||
|
|
d145e78cd6 | ||
|
|
01d359c1df | ||
|
|
7d628ef76c | ||
|
|
7553d5892e | ||
|
|
6a01d6e7d3 | ||
|
|
1fb663b429 | ||
|
|
3489a45216 | ||
|
|
294beceec7 | ||
|
|
0f21e46586 | ||
|
|
547b2a2e37 | ||
|
|
950a9a72ab | ||
|
|
b3060956c3 | ||
|
|
9a19cc8323 | ||
|
|
118dcf27ce | ||
|
|
9ff737efbd | ||
|
|
f211a3bb69 | ||
|
|
ef5b1c8f5f | ||
|
|
a2ed1a4197 | ||
|
|
a71b2f0a93 | ||
|
|
2a873be9cd | ||
|
|
599bd1a6aa | ||
|
|
f8a959da05 | ||
|
|
e24eeefbd1 | ||
|
|
ca072c9fc6 | ||
|
|
de5b8a1c45 | ||
|
|
7ad4911584 | ||
|
|
616c21d730 | ||
|
|
80af7d3ccd | ||
|
|
d17b8412f1 | ||
|
|
04af745fec | ||
|
|
c94da8977d | ||
|
|
9a1745f2c8 | ||
|
|
720a9d0636 | ||
|
|
7324823b3e | ||
|
|
b09b557fc6 | ||
|
|
f5e72c8709 | ||
|
|
0da649eb72 | ||
|
|
49134ecf25 | ||
|
|
05887f2087 | ||
|
|
eedc0b19fd | ||
|
|
4560fae07e | ||
|
|
a6351ac474 | ||
|
|
dc5b136930 | ||
|
|
0b1eb4c841 | ||
|
|
5ad9b6b317 | ||
|
|
ea8e66ccd1 | ||
|
|
6493be9eea | ||
|
|
641deb9c0e | ||
|
|
05ce978e18 | ||
|
|
97e2951875 | ||
|
|
4db63e323e | ||
|
|
63cb046d38 | ||
|
|
0882623092 | ||
|
|
889e4787d6 | ||
|
|
3336aa95f1 | ||
|
|
b695e5c24b | ||
|
|
fc6f97f162 | ||
|
|
eb87a36940 | ||
|
|
6c4f2bd83d | ||
|
|
a82e8a701d | ||
|
|
28849fd789 | ||
|
|
524739900a | ||
|
|
aafbf7183f | ||
|
|
3a59163614 | ||
|
|
6a510d6174 | ||
|
|
ca569bb837 | ||
|
|
de5d8616bf | ||
|
|
d97e8bd49b | ||
|
|
b46e26e65a | ||
|
|
b6f67dd2b2 | ||
|
|
09f00e397c | ||
|
|
446fb65ca6 | ||
|
|
b3dd0995df | ||
|
|
1502c2fd8b | ||
|
|
0d2f081d41 | ||
|
|
45a1cfde1f | ||
|
|
2f5279eb01 | ||
|
|
c21b7f8cb8 | ||
|
|
a7147f327f | ||
|
|
0773e88df5 | ||
|
|
8b64dd67d2 | ||
|
|
d9ca0457b5 | ||
|
|
a76fb7b2fb | ||
|
|
3b80fcd1a0 | ||
|
|
b3612f6462 | ||
|
|
8b8c51573b | ||
|
|
84fac6ca44 | ||
|
|
bf0752a8d7 | ||
|
|
c4cef905ae | ||
|
|
cecf4b0d4e | ||
|
|
78f9cb44c3 | ||
|
|
3383436068 | ||
|
|
2d14a237dc | ||
|
|
a57757aaba | ||
|
|
933beeb18b | ||
|
|
965ac7f406 | ||
|
|
90242312fe | ||
|
|
b305534edc | ||
|
|
be1d44279c | ||
|
|
f6c3af9c8c | ||
|
|
0c4c4cfd16 | ||
|
|
f773da2273 | ||
|
|
8ca8887885 | ||
|
|
f5966890b0 | ||
|
|
01aa1882f8 | ||
|
|
5ad12c47dc | ||
|
|
766532948e | ||
|
|
4e8f93c6f1 | ||
|
|
b4eaf9d96f | ||
|
|
0ea20a5f86 | ||
|
|
33f1008d01 | ||
|
|
7381a2b072 | ||
|
|
e08edab180 | ||
|
|
ffd0ca4391 | ||
|
|
e7e2b26b2e | ||
|
|
a0fa64a91c | ||
|
|
acaf53926c | ||
|
|
38df1c3138 | ||
|
|
093fbfd867 | ||
|
|
ac0915bdb5 | ||
|
|
537e92b158 | ||
|
|
51b401d418 | ||
|
|
1506c40ec8 | ||
|
|
404ec13fbb | ||
|
|
5c56cf110b | ||
|
|
3149533f0c | ||
|
|
d2c6aeea7d | ||
|
|
c959f9f0d8 | ||
|
|
42ce72be3c | ||
|
|
be781fc8f5 | ||
|
|
39aedcef64 |
19
.github/workflows/create-test-plan.py
vendored
19
.github/workflows/create-test-plan.py
vendored
@@ -100,6 +100,7 @@ class JobSpec:
|
||||
clang_cl: bool = False
|
||||
gdk: bool = False
|
||||
vita_gles: Optional[VitaGLES] = None
|
||||
more_hard_deps: bool = False
|
||||
|
||||
|
||||
JOB_SPECS = {
|
||||
@@ -116,8 +117,8 @@ JOB_SPECS = {
|
||||
"ubuntu-22.04": JobSpec(name="Ubuntu 22.04", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04", ),
|
||||
"ubuntu-latest": JobSpec(name="Ubuntu (latest)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-ubuntu-latest", ),
|
||||
"ubuntu-24.04-arm64": JobSpec(name="Ubuntu 24.04 (ARM64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-ubuntu24.04-arm64", ),
|
||||
"steamrt3": JobSpec(name="Steam Linux Runtime 3.0 (x86_64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-steamrt3", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest", ),
|
||||
"steamrt3-arm64": JobSpec(name="Steam Linux Runtime 3.0 (arm64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-steamrt3-arm64", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk/arm64:latest", ),
|
||||
"steamrt3": JobSpec(name="Steam Linux Runtime 3.0 (x86_64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-steamrt3", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest", more_hard_deps = True, ),
|
||||
"steamrt3-arm64": JobSpec(name="Steam Linux Runtime 3.0 (arm64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-steamrt3-arm64", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk/arm64:latest", more_hard_deps = True, ),
|
||||
"ubuntu-intel-icx": JobSpec(name="Ubuntu 22.04 (Intel oneAPI)", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04-oneapi", intel=IntelCompiler.Icx, ),
|
||||
"ubuntu-intel-icc": JobSpec(name="Ubuntu 22.04 (Intel Compiler)", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04-icc", intel=IntelCompiler.Icc, ),
|
||||
"macos-framework-x64": JobSpec(name="MacOS (Framework) (x64)", os=JobOs.Macos14, platform=SdlPlatform.MacOS, artifact="SDL-macos-framework", apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, xcode=True, ),
|
||||
@@ -448,6 +449,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
"libxfixes-dev",
|
||||
"libxi-dev",
|
||||
"libxss-dev",
|
||||
"libxtst-dev",
|
||||
"libwayland-dev",
|
||||
"libxkbcommon-dev",
|
||||
"libdrm-dev",
|
||||
@@ -483,6 +485,19 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
|
||||
job.shared_lib = SharedLibType.SO_0
|
||||
job.static_lib = StaticLibType.A
|
||||
fpic = True
|
||||
if spec.more_hard_deps:
|
||||
# Some distros prefer to make important dependencies
|
||||
# mandatory, so that SDL won't start up but lack expected
|
||||
# functionality if they're missing
|
||||
job.cmake_arguments.extend([
|
||||
"-DSDL_ALSA_SHARED=OFF",
|
||||
"-DSDL_FRIBIDI_SHARED=OFF",
|
||||
"-DSDL_HIDAPI_LIBUSB_SHARED=OFF",
|
||||
"-DSDL_PULSEAUDIO_SHARED=OFF",
|
||||
"-DSDL_X11_SHARED=OFF",
|
||||
"-DSDL_WAYLAND_LIBDECOR_SHARED=OFF",
|
||||
"-DSDL_WAYLAND_SHARED=OFF",
|
||||
])
|
||||
case SdlPlatform.Ios | SdlPlatform.Tvos:
|
||||
job.brew_packages.extend([
|
||||
"ccache",
|
||||
|
||||
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@@ -91,13 +91,21 @@ jobs:
|
||||
sudo apt-get install -y \
|
||||
gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev \
|
||||
libusb-1.0-0-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev \
|
||||
libxss-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
|
||||
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
|
||||
libxss-dev libxtst-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev \
|
||||
libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
|
||||
- name: 'CMake (configure + build + tests + examples)'
|
||||
run: |
|
||||
set -e
|
||||
cmake -S ${{ steps.tar.outputs.path }} -B /tmp/build -DSDL_TEST_LIBRARY=TRUE -DSDL_TESTS=TRUE -DSDL_EXAMPLES=TRUE
|
||||
cmake --build /tmp/build --verbose
|
||||
ctest --test-dir /tmp/build --no-tests=error --output-on-failure
|
||||
- name: 'Verify SDL_REVISION contains SDL-'
|
||||
run: |
|
||||
set -e
|
||||
if test "x$(strings /tmp/build/libSDL3.so.0 | grep SDL- | wc -l)" != x1; then
|
||||
echo "SDL- string not found: must be present in SDL_REVISION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dmg:
|
||||
needs: [src]
|
||||
@@ -677,6 +685,7 @@ jobs:
|
||||
-DTEST_TEST=TRUE \
|
||||
-DCMAKE_PREFIX_PATH="${{ steps.sdk.outputs.prefix }}" \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_USE_LEGACY_TOOLCHAIN=0 \
|
||||
-DANDROID_ABI=${android_abi} \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-B "${android_abi}"
|
||||
|
||||
@@ -112,8 +112,6 @@ ifeq ($(NDK_DEBUG),1)
|
||||
cmd-strip :=
|
||||
endif
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := cpufeatures
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
||||
@@ -145,4 +143,3 @@ LOCAL_EXPORT_LDLIBS :=
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
$(call import-module,android/cpufeatures)
|
||||
|
||||
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
|
||||
# See docs/release_checklist.md
|
||||
project(SDL3 LANGUAGES C VERSION "3.3.2")
|
||||
project(SDL3 LANGUAGES C VERSION "3.3.4")
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
set(SDL3_MAINPROJECT ON)
|
||||
@@ -169,12 +169,12 @@ else()
|
||||
endif()
|
||||
|
||||
set(SDL_ASSEMBLY_DEFAULT OFF)
|
||||
if(USE_CLANG OR USE_GCC OR USE_INTELCC OR MSVC_VERSION GREATER 1400)
|
||||
if(USE_CLANG OR USE_GCC OR USE_INTELCC OR USE_TCC OR MSVC_VERSION GREATER 1400)
|
||||
set(SDL_ASSEMBLY_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
set(SDL_GCC_ATOMICS_DEFAULT OFF)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC OR USE_TCC)
|
||||
set(SDL_GCC_ATOMICS_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
@@ -349,6 +349,8 @@ dep_option(SDL_X11_XSYNC "Enable Xsync support" ON SDL_X11 OFF)
|
||||
dep_option(SDL_X11_XTEST "Enable XTest support" ON SDL_X11 OFF)
|
||||
dep_option(SDL_FRIBIDI "Enable Fribidi support" ON SDL_X11 OFF)
|
||||
dep_option(SDL_FRIBIDI_SHARED "Dynamically load Fribidi support" ON "SDL_FRIBIDI;SDL_DEPS_SHARED" OFF)
|
||||
dep_option(SDL_LIBTHAI "Enable Thai support" ON SDL_X11 OFF)
|
||||
dep_option(SDL_LIBTHAI_SHARED "Dynamically load Thai support" ON "SDL_LIBTHAI;SDL_DEPS_SHARED" OFF)
|
||||
dep_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS} "SDL_VIDEO" OFF)
|
||||
dep_option(SDL_WAYLAND_SHARED "Dynamically load Wayland support" ON "SDL_WAYLAND;SDL_DEPS_SHARED" OFF)
|
||||
dep_option(SDL_WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF)
|
||||
@@ -463,7 +465,10 @@ if(SDL_SHARED)
|
||||
if ("c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES)
|
||||
target_compile_features(SDL3-shared PRIVATE c_std_99)
|
||||
else()
|
||||
message(WARNING "target_compile_features does not know c_std_99 for C compiler")
|
||||
# tcc does support the subset of C99 used by SDL
|
||||
if (NOT USE_TCC)
|
||||
message(WARNING "target_compile_features does not know c_std_99 for C compiler")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -476,7 +481,9 @@ if(SDL_STATIC)
|
||||
if ("c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES)
|
||||
target_compile_features(SDL3-static PRIVATE c_std_99)
|
||||
else()
|
||||
message(WARNING "target_compile_features does not know c_std_99 for C compiler")
|
||||
if (NOT USE_TCC)
|
||||
message(WARNING "target_compile_features does not know c_std_99 for C compiler")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -510,7 +517,10 @@ check_linker_supports_version_file(HAVE_WL_VERSION_SCRIPT)
|
||||
if(HAVE_WL_VERSION_SCRIPT)
|
||||
sdl_shared_link_options("-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/dynapi/SDL_dynapi.sym")
|
||||
else()
|
||||
if((LINUX AND LIBC_IS_GLIBC) OR ANDROID)
|
||||
# When building with tcc on Linux+glibc or Android, avoid emitting an error
|
||||
# for lack of support of the version-script linker flag: the option will be
|
||||
# silently ignored by the compiler and the build will still succeed.
|
||||
if(((LINUX AND LIBC_IS_GLIBC) OR ANDROID) AND (NOT USE_TCC))
|
||||
message(FATAL_ERROR "Linker does not support '-Wl,--version-script=xxx.sym'. This is required on the current host platform (${SDL_CMAKE_PLATFORM}).")
|
||||
endif()
|
||||
endif()
|
||||
@@ -914,6 +924,7 @@ if(SDL_ASSEMBLY)
|
||||
set(HAVE_ALTIVEC TRUE)
|
||||
set(SDL_ALTIVEC_BLITTERS 1)
|
||||
sdl_compile_options(PRIVATE "-maltivec")
|
||||
sdl_compile_options(PRIVATE "-fno-tree-vectorize")
|
||||
set_property(SOURCE "${SDL3_SOURCE_DIR}/src/video/SDL_blit_N.c" APPEND PROPERTY COMPILE_DEFINITIONS "SDL_ENABLE_ALTIVEC")
|
||||
set_property(SOURCE "${SDL3_SOURCE_DIR}/src/video/SDL_blit_N.c" PROPERTY SKIP_PRECOMPILE_HEADERS 1)
|
||||
endif()
|
||||
@@ -931,7 +942,17 @@ if(SDL_ASSEMBLY)
|
||||
cmake_pop_check_state()
|
||||
|
||||
if(COMPILER_SUPPORTS_LSX AND HAVE_LSXINTRIN_H)
|
||||
set_property(SOURCE "${SDL3_SOURCE_DIR}/src/video/yuv2rgb/yuv_rgb_lsx.c" APPEND PROPERTY COMPILE_OPTIONS "-mlsx")
|
||||
set_property(SOURCE
|
||||
"${SDL3_SOURCE_DIR}/src/video/yuv2rgb/yuv_rgb_lsx.c"
|
||||
"${SDL3_SOURCE_DIR}/src/video/SDL_blit_A.c"
|
||||
"${SDL3_SOURCE_DIR}/src/video/SDL_fillrect.c"
|
||||
APPEND PROPERTY COMPILE_OPTIONS "-mlsx")
|
||||
|
||||
set_property(SOURCE
|
||||
"${SDL3_SOURCE_DIR}/src/video/yuv2rgb/yuv_rgb_lsx.c"
|
||||
"${SDL3_SOURCE_DIR}/src/video/SDL_blit_A.c"
|
||||
"${SDL3_SOURCE_DIR}/src/video/SDL_fillrect.c"
|
||||
PROPERTY SKIP_PRECOMPILE_HEADERS 1)
|
||||
set(HAVE_LSX TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1396,8 +1417,6 @@ if(ANDROID)
|
||||
"${SDL3_SOURCE_DIR}/src/core/android/*.c"
|
||||
"${SDL3_SOURCE_DIR}/src/core/android/*.h"
|
||||
)
|
||||
sdl_sources("${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
|
||||
set_property(SOURCE "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
|
||||
|
||||
sdl_glob_sources(
|
||||
"${SDL3_SOURCE_DIR}/src/misc/android/*.c"
|
||||
@@ -1715,6 +1734,15 @@ elseif(EMSCRIPTEN)
|
||||
set(HAVE_CLOCK_GETTIME 1)
|
||||
endif()
|
||||
|
||||
if(SDL_SENSOR)
|
||||
set(SDL_SENSOR_EMSCRIPTEN 1)
|
||||
set(HAVE_SDL_SENSORS TRUE)
|
||||
sdl_glob_sources(
|
||||
"${SDL3_SOURCE_DIR}/src/sensor/emscripten/*.c"
|
||||
"${SDL3_SOURCE_DIR}/src/sensor/emscripten/*.h"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(SDL_VIDEO)
|
||||
set(SDL_VIDEO_DRIVER_EMSCRIPTEN 1)
|
||||
sdl_glob_sources(
|
||||
@@ -1787,6 +1815,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
||||
CheckROCKCHIP()
|
||||
CheckX11()
|
||||
CheckFribidi()
|
||||
CheckLibThai()
|
||||
# Need to check for EGL first because KMSDRM and Wayland depend on it.
|
||||
CheckEGL()
|
||||
CheckKMSDRM()
|
||||
@@ -3452,7 +3481,10 @@ int main(void)
|
||||
return 0;
|
||||
}
|
||||
" HAVE_POSIX_SPAWN)
|
||||
if(HAVE_POSIX_SPAWN)
|
||||
if(NOT APPLE)
|
||||
check_symbol_exists(vfork "unistd.h" LIBC_HAS_VFORK)
|
||||
endif()
|
||||
if(HAVE_POSIX_SPAWN AND (APPLE OR LIBC_HAS_VFORK))
|
||||
sdl_glob_sources(
|
||||
"${SDL3_SOURCE_DIR}/src/process/posix/*.c"
|
||||
"${SDL3_SOURCE_DIR}/src/process/posix/*.h"
|
||||
@@ -3796,10 +3828,6 @@ else()
|
||||
set(ARCH_64 FALSE)
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
sdl_include_directories(PRIVATE SYSTEM "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
cmake_push_check_state(RESET)
|
||||
check_c_compiler_flag(-fobjc-arc COMPILER_SUPPORTS_FOBJC_ARC)
|
||||
|
||||
@@ -735,6 +735,7 @@
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_triton.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch2.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_wii.c" />
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_triton.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch2.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_wii.c" />
|
||||
|
||||
@@ -82,16 +82,16 @@
|
||||
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x86;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(ProjectDir)/../../src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)/../../src;$(ProjectDir)/../../src/core/windows;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(ProjectDir)/../../src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)/../../src;$(ProjectDir)/../../src/core/windows;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(ProjectDir)/../../src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)/../../src;$(ProjectDir)/../../src/core/windows;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(ProjectDir)/../../src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)/../../src;$(ProjectDir)/../../src/core/windows;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PreBuildEvent>
|
||||
@@ -625,6 +625,7 @@
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_triton.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch2.c" />
|
||||
|
||||
@@ -1538,8 +1538,6 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sensor\windows\SDL_windowssensor.c">
|
||||
<Filter>sensor\windows</Filter>
|
||||
</ClCompile>
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\render\SDL_render.c">
|
||||
<Filter>render</Filter>
|
||||
@@ -1660,6 +1658,9 @@
|
||||
<ClCompile Include="..\..\src\storage\generic\SDL_genericstorage.c" />
|
||||
<ClCompile Include="..\..\src\storage\steam\SDL_steamstorage.c" />
|
||||
<ClCompile Include="..\..\src\storage\SDL_storage.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_triton.c">
|
||||
<Filter>joystick\hidapi</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\events\SDL_eventwatch.c" />
|
||||
<ClCompile Include="..\..\src\core\windows\pch_cpp.cpp">
|
||||
<Filter>core\windows</Filter>
|
||||
|
||||
@@ -49,27 +49,33 @@ Emscripten:
|
||||
PlayStation 2:
|
||||
* Added the following hints to control the display parameters: SDL_HINT_PS2_GS_WIDTH, SDL_HINT_PS2_GS_HEIGHT, SDL_HINT_PS2_GS_PROGRESSIVE, SDL_HINT_PS2_GS_MODE
|
||||
|
||||
Note: On Unix platforms SDL provides ELF notes describing its non-mandatory library dependencies in the format described by https://systemd.io/ELF_DLOPEN_METADATA/. Some of these libraries are quite important, so distribution vendors who package SDL should parse the ELF notes and consider generating dependencies at the packaging level, for example by using https://github.com/systemd/package-notes. Other libraries and games can add similar ELF notes to describe their own dependencies by using the SDL_ELF_NOTE_DLOPEN macro.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
3.2.22:
|
||||
---------------------------------------------------------------------------
|
||||
* SDL_HINT_JOYSTICK_WGI is disabled by default
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
3.2.16:
|
||||
---------------------------------------------------------------------------
|
||||
* SDL_HINT_JOYSTICK_RAWINPUT is disabled by default
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
3.2.10:
|
||||
---------------------------------------------------------------------------
|
||||
* Added SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT to control whether XSelectInput() should be called on external windows to enable input events.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
3.2.4:
|
||||
---------------------------------------------------------------------------
|
||||
* Added SDL_StretchSurface()
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
3.2.0:
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.3.2</string>
|
||||
<string>3.3.4</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>SDLX</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3.3.2</string>
|
||||
<string>3.3.4</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -415,6 +415,7 @@
|
||||
F386F6F92884663E001840AA /* SDL_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = F386F6E62884663E001840AA /* SDL_utils.c */; };
|
||||
F388C95528B5F6F700661ECF /* SDL_hidapi_ps3.c in Sources */ = {isa = PBXBuildFile; fileRef = F388C95428B5F6F600661ECF /* SDL_hidapi_ps3.c */; };
|
||||
F39344CE2E99771B0056986F /* SDL_dlopennote.h in Headers */ = {isa = PBXBuildFile; fileRef = F39344CD2E99771B0056986F /* SDL_dlopennote.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F38C72492CEEB1DE000B0A90 /* SDL_hidapi_steam_triton.c in Sources */ = {isa = PBXBuildFile; fileRef = F38C72482CEEB1DE000B0A90 /* SDL_hidapi_steam_triton.c */; };
|
||||
F395BF6525633B2400942BFF /* SDL_crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = F395BF6425633B2400942BFF /* SDL_crc32.c */; };
|
||||
F395C1932569C68F00942BFF /* SDL_iokitjoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F395C1912569C68E00942BFF /* SDL_iokitjoystick_c.h */; };
|
||||
F395C19C2569C68F00942BFF /* SDL_iokitjoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = F395C1922569C68E00942BFF /* SDL_iokitjoystick.c */; };
|
||||
@@ -998,6 +999,7 @@
|
||||
F386F6E62884663E001840AA /* SDL_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_utils.c; sourceTree = "<group>"; };
|
||||
F388C95428B5F6F600661ECF /* SDL_hidapi_ps3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_ps3.c; sourceTree = "<group>"; };
|
||||
F39344CD2E99771B0056986F /* SDL_dlopennote.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_dlopennote.h; sourceTree = "<group>"; };
|
||||
F38C72482CEEB1DE000B0A90 /* SDL_hidapi_steam_triton.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_steam_triton.c; sourceTree = "<group>"; };
|
||||
F395BF6425633B2400942BFF /* SDL_crc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_crc32.c; sourceTree = "<group>"; };
|
||||
F395C1912569C68E00942BFF /* SDL_iokitjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_iokitjoystick_c.h; sourceTree = "<group>"; };
|
||||
F395C1922569C68E00942BFF /* SDL_iokitjoystick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_iokitjoystick.c; sourceTree = "<group>"; };
|
||||
@@ -1962,6 +1964,7 @@
|
||||
F3984CCF25BCC92800374F43 /* SDL_hidapi_stadia.c */,
|
||||
A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */,
|
||||
F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */,
|
||||
F38C72482CEEB1DE000B0A90 /* SDL_hidapi_steam_triton.c */,
|
||||
A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */,
|
||||
A7D8A7C623E2513E00DCD162 /* SDL_hidapi_switch.c */,
|
||||
A7D8A7C623E2513E00DCD163 /* SDL_hidapi_switch2.c */,
|
||||
@@ -3009,6 +3012,7 @@
|
||||
F316ABD92B5C3185002EF551 /* SDL_memcpy.c in Sources */,
|
||||
A7D8B97A23E2514400DCD162 /* SDL_render.c in Sources */,
|
||||
A7D8ABD323E2514100DCD162 /* SDL_stretch.c in Sources */,
|
||||
F38C72492CEEB1DE000B0A90 /* SDL_hidapi_steam_triton.c in Sources */,
|
||||
A7D8AC3923E2514100DCD162 /* SDL_blit_copy.c in Sources */,
|
||||
A7D8B5CF23E2514300DCD162 /* SDL_syspower.m in Sources */,
|
||||
F3B439512C935C2400792030 /* SDL_dummyprocess.c in Sources */,
|
||||
@@ -3141,8 +3145,8 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEPLOYMENT_POSTPROCESSING = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 303.0.0;
|
||||
DYLIB_CURRENT_VERSION = 303.0.0;
|
||||
DYLIB_COMPATIBILITY_VERSION = 305.0.0;
|
||||
DYLIB_CURRENT_VERSION = 305.0.0;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
@@ -3177,7 +3181,7 @@
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.3.2;
|
||||
MARKETING_VERSION = 3.3.4;
|
||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||
PRODUCT_NAME = SDL3;
|
||||
@@ -3207,8 +3211,8 @@
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 303.0.0;
|
||||
DYLIB_CURRENT_VERSION = 303.0.0;
|
||||
DYLIB_COMPATIBILITY_VERSION = 305.0.0;
|
||||
DYLIB_CURRENT_VERSION = 305.0.0;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -3240,7 +3244,7 @@
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.3.2;
|
||||
MARKETING_VERSION = 3.3.4;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Title SDL 3.3.2
|
||||
Title SDL 3.3.4
|
||||
Version 1
|
||||
Description SDL Library for macOS (http://www.libsdl.org)
|
||||
DefaultLocation /Library/Frameworks
|
||||
|
||||
@@ -31,9 +31,11 @@ if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re)
|
||||
set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}")
|
||||
else()
|
||||
message(AUTHOR_WARNING "Could not extract version from SDL_version.h.")
|
||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
unset(_sdl_version_h)
|
||||
unset(_sdl_version_h_path)
|
||||
unset(_sdl_major_re)
|
||||
unset(_sdl_major)
|
||||
|
||||
@@ -16,6 +16,7 @@ set(_sdl3_version_h "${_sdl3_framework}/Headers/SDL_version.h")
|
||||
|
||||
if(NOT EXISTS "${_sdl3_version_h}")
|
||||
message(AUTHOR_WARNING "Cannot not find ${_sdl3_framework}. This script is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework")
|
||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -36,6 +37,7 @@ if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re)
|
||||
set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}")
|
||||
else()
|
||||
message(AUTHOR_WARNING "Could not extract version from SDL_version.h.")
|
||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1991,7 +1991,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testatomic;
|
||||
productName = testalpha;
|
||||
productReference = 0017958C10741F7900F5D044 /* testatomic.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2008,7 +2007,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testaudioinfo;
|
||||
productName = testalpha;
|
||||
productReference = 001795AD107421BF00F5D044 /* testaudioinfo.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2025,7 +2023,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testgl;
|
||||
productName = testalpha;
|
||||
productReference = 0017972110742F3200F5D044 /* testgl.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2042,7 +2039,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testhaptic;
|
||||
productName = testalpha;
|
||||
productReference = 00179748107430D600F5D044 /* testhaptic.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2059,7 +2055,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testdraw;
|
||||
productName = testalpha;
|
||||
productReference = 0017976E107431B300F5D044 /* testdraw.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2077,7 +2072,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testime;
|
||||
productName = testalpha;
|
||||
productReference = 0017978E107432AE00F5D044 /* testime.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2094,7 +2088,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testintersections;
|
||||
productName = testalpha;
|
||||
productReference = 001797AE1074334C00F5D044 /* testintersections.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2111,7 +2104,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testloadso;
|
||||
productName = testalpha;
|
||||
productReference = 001797D0107433C600F5D044 /* testloadso.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2129,7 +2121,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testmultiaudio;
|
||||
productName = testalpha;
|
||||
productReference = 001798121074355200F5D044 /* testmultiaudio.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2147,7 +2138,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testnative;
|
||||
productName = testalpha;
|
||||
productReference = 001798941074392D00F5D044 /* testnative.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2164,7 +2154,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testpower;
|
||||
productName = testalpha;
|
||||
productReference = 001798B5107439DF00F5D044 /* testpower.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2181,7 +2170,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testresample;
|
||||
productName = testalpha;
|
||||
productReference = 001798F210743BEC00F5D044 /* testresample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2199,7 +2187,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testsprite;
|
||||
productName = testalpha;
|
||||
productReference = 0017991610743F1000F5D044 /* testsprite.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2216,7 +2203,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testwm;
|
||||
productName = testalpha;
|
||||
productReference = 0017993810743FB700F5D044 /* testwm.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2233,7 +2219,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testfile;
|
||||
productName = testalpha;
|
||||
productReference = 002F341209CA1BFF00EBEB88 /* testfile.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2251,7 +2236,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testiconv;
|
||||
productName = testalpha;
|
||||
productReference = 002F343109CA1F0300EBEB88 /* testiconv.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2269,7 +2253,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testoverlay;
|
||||
productName = testalpha;
|
||||
productReference = 002F344D09CA1FB300EBEB88 /* testoverlay.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2286,7 +2269,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testplatform;
|
||||
productName = testalpha;
|
||||
productReference = 002F346A09CA204F00EBEB88 /* testplatform.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2509,7 +2491,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testdrawchessboard;
|
||||
productName = testalpha;
|
||||
productReference = DB0F48EC17CA51E5008798C5 /* testdrawchessboard.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2526,7 +2507,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testfilesystem;
|
||||
productName = testalpha;
|
||||
productReference = DB0F490117CA5212008798C5 /* testfilesystem.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2560,7 +2540,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testmessage;
|
||||
productName = testalpha;
|
||||
productReference = DB166DD516A1D36A00A1396C /* testmessage.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2577,7 +2556,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testrelative;
|
||||
productName = testalpha;
|
||||
productReference = DB166DEE16A1D50C00A1396C /* testrelative.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2595,7 +2573,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testrendercopyex;
|
||||
productName = testalpha;
|
||||
productReference = DB166E0516A1D57C00A1396C /* testrendercopyex.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2613,7 +2590,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testrendertarget;
|
||||
productName = testalpha;
|
||||
productReference = DB166E1C16A1D5AD00A1396C /* testrendertarget.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2630,7 +2606,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testrumble;
|
||||
productName = testalpha;
|
||||
productReference = DB166E3816A1D64D00A1396C /* testrumble.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2648,7 +2623,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testscale;
|
||||
productName = testalpha;
|
||||
productReference = DB166E5216A1D69000A1396C /* testscale.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2717,7 +2691,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testhotplug;
|
||||
productName = testalpha;
|
||||
productReference = DB89957E18A19ABA0092407C /* testhotplug.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2734,7 +2707,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testautomation;
|
||||
productName = testalpha;
|
||||
productReference = F35E56AA298312CB00A43A5F /* testautomation.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2751,7 +2723,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testcamera;
|
||||
productName = testalpha;
|
||||
productReference = F36C34272C0F85DB00991150 /* testcamera.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2768,7 +2739,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testpen;
|
||||
productName = testalpha;
|
||||
productReference = F3B7FD6A2D73FC630086D1D0 /* testpen.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -2803,7 +2773,6 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = testyuv;
|
||||
productName = testalpha;
|
||||
productReference = F3DB65E92E9DA90000568044 /* testyuv.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
@@ -4045,7 +4014,7 @@
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
HEADER_SEARCH_PATHS = ../../include;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
@@ -4056,7 +4025,8 @@
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros macosx iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
TVOS_DEPLOYMENT_TARGET = 11.0;
|
||||
XROS_DEPLOYMENT_TARGET = 1.3;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -4219,7 +4189,7 @@
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
HEADER_SEARCH_PATHS = ../../include;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
@@ -4229,7 +4199,8 @@
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros macosx iphonesimulator iphoneos appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
TVOS_DEPLOYMENT_TARGET = 11.0;
|
||||
XROS_DEPLOYMENT_TARGET = 1.3;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -4726,6 +4697,25 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F37E49E22EB5250B00E508F7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F37E49E32EB5250B00E508F7 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F3B7FD682D73FC630086D1D0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -5213,8 +5203,8 @@
|
||||
F3DB65E62E9DA90000568044 /* Build configuration list for PBXNativeTarget "testyuv" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F3DB65E72E9DA90000568044 /* Debug */,
|
||||
F3DB65E82E9DA90000568044 /* Release */,
|
||||
F37E49E22EB5250B00E508F7 /* Debug */,
|
||||
F37E49E32EB5250B00E508F7 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Debug;
|
||||
|
||||
@@ -10,5 +10,7 @@
|
||||
// This allows you to set DEVELOPMENT_TEAM for all targets, for example.
|
||||
#include? "build.xcconfig"
|
||||
|
||||
INFOPLIST_FILE = test-Info.plist
|
||||
|
||||
CONFIG_FRAMEWORK_LDFLAGS = -lSDL3_test
|
||||
|
||||
|
||||
20
Xcode/SDLTest/test-Info.plist
Normal file
20
Xcode/SDLTest/test-Info.plist
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UILaunchScreen</key>
|
||||
<dict>
|
||||
<key>UIColorName</key>
|
||||
<string></string>
|
||||
<key>UIImageName</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 3;
|
||||
private static final int SDL_MINOR_VERSION = 3;
|
||||
private static final int SDL_MICRO_VERSION = 2;
|
||||
private static final int SDL_MICRO_VERSION = 4;
|
||||
/*
|
||||
// Display InputType.SOURCE/CLASS of events and devices
|
||||
//
|
||||
|
||||
@@ -1028,6 +1028,7 @@ class Releaser:
|
||||
# NDK 21e does not support -ffile-prefix-map
|
||||
# f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
|
||||
# f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
|
||||
f"-DANDROID_USE_LEGACY_TOOLCHAIN=0",
|
||||
f"-DCMAKE_EXE_LINKER_FLAGS={extra_link_options}",
|
||||
f"-DCMAKE_SHARED_LINKER_FLAGS={extra_link_options}",
|
||||
f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}",
|
||||
@@ -1126,8 +1127,7 @@ class Releaser:
|
||||
for dep, depinfo in self.release_info.get("dependencies", {}).items():
|
||||
startswith = depinfo["startswith"]
|
||||
dep_repo = depinfo["repo"]
|
||||
# FIXME: dropped "--exclude-pre-releases"
|
||||
dep_string_data = self.executer.check_output(["gh", "-R", dep_repo, "release", "list", "--exclude-drafts", "--json", "name,createdAt,tagName", "--jq", f'[.[]|select(.name|startswith("{startswith}"))]|max_by(.createdAt)']).strip()
|
||||
dep_string_data = self.executer.check_output(["gh", "-R", dep_repo, "release", "list", "--exclude-drafts", "--exclude-pre-releases", "--json", "name,createdAt,tagName", "--jq", f'[.[]|select(.name|startswith("{startswith}"))]|max_by(.createdAt)']).strip()
|
||||
dep_data = json.loads(dep_string_data)
|
||||
dep_tag = dep_data["tagName"]
|
||||
dep_version = dep_data["name"]
|
||||
|
||||
@@ -29,7 +29,7 @@ import sys
|
||||
|
||||
SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
|
||||
STDLIB_SYMBOLS = [
|
||||
STDLIB_SYMBOLS = (
|
||||
'abs',
|
||||
'acos',
|
||||
'acosf',
|
||||
@@ -147,8 +147,8 @@ STDLIB_SYMBOLS = [
|
||||
'wcsncasecmp',
|
||||
'wcsncmp',
|
||||
'wcsstr',
|
||||
]
|
||||
RE_STDLIB_SYMBOL = re.compile(rf"\b(?P<symbol>{'|'.join(STDLIB_SYMBOLS)})\b\(")
|
||||
)
|
||||
RE_STDLIB_SYMBOL = re.compile(rf"(?<!->)\b(?P<symbol>{'|'.join(STDLIB_SYMBOLS)})\b\(")
|
||||
|
||||
|
||||
def find_symbols_in_file(file: pathlib.Path) -> int:
|
||||
@@ -220,13 +220,19 @@ def find_symbols_in_file(file: pathlib.Path) -> int:
|
||||
line_comment += line[pos_line_comment:]
|
||||
line = line[:pos_line_comment]
|
||||
|
||||
if m := RE_STDLIB_SYMBOL.match(line):
|
||||
override_string = f"This should NOT be SDL_{m['symbol']}()"
|
||||
if override_string not in line_comment:
|
||||
print(f"{filename}:{line_i}")
|
||||
print(f" {line}")
|
||||
print(f"")
|
||||
match_count += 1
|
||||
if matches := tuple(RE_STDLIB_SYMBOL.finditer(line)):
|
||||
text_string = " or ".join(f"SDL_{m.group(1)}" for m in matches)
|
||||
first_quote = line.find("\"")
|
||||
last_quote = line.rfind("\"")
|
||||
first_occurrence = min(m.span()[0] for m in matches)
|
||||
last_occurrence = max(m.span()[1] for m in matches)
|
||||
if first_quote == -1 or not (first_quote < first_occurrence and last_quote > last_occurrence):
|
||||
override_string = f"This should NOT be {text_string}"
|
||||
if override_string not in line_comment:
|
||||
print(f"{filename}:{line_i}")
|
||||
print(f" {line}")
|
||||
print(f"")
|
||||
match_count += 1
|
||||
|
||||
except UnicodeDecodeError:
|
||||
print(f"{file} is not text, skipping", file=sys.stderr)
|
||||
@@ -235,7 +241,7 @@ def find_symbols_in_file(file: pathlib.Path) -> int:
|
||||
|
||||
def find_symbols_in_dir(path: pathlib.Path) -> int:
|
||||
match_count = 0
|
||||
for entry in path.glob("*"):
|
||||
for entry in path.iterdir():
|
||||
if entry.is_dir():
|
||||
match_count += find_symbols_in_dir(entry)
|
||||
else:
|
||||
@@ -249,7 +255,10 @@ def main():
|
||||
|
||||
print(f"Looking for stdlib usage in {args.path}...")
|
||||
|
||||
match_count = find_symbols_in_dir(args.path)
|
||||
if args.path.is_file():
|
||||
match_count = find_symbols_in_file(args.path)
|
||||
else:
|
||||
match_count = find_symbols_in_dir(args.path)
|
||||
|
||||
if match_count:
|
||||
print("If the stdlib usage is intentional, add a '// This should NOT be SDL_<symbol>()' line comment.")
|
||||
|
||||
142
build-scripts/create_tbds.py
Executable file
142
build-scripts/create_tbds.py
Executable file
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import dataclasses
|
||||
import enum
|
||||
from pathlib import Path
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
SDL_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TbdInfo:
|
||||
install_name: str
|
||||
target_infos: list[dict[str, str]]
|
||||
|
||||
|
||||
class TbdPlatform(enum.StrEnum):
|
||||
MACOS = "macOS"
|
||||
IOS = "iOS"
|
||||
|
||||
|
||||
TBDINFOS = {
|
||||
TbdPlatform.MACOS: TbdInfo(
|
||||
install_name="@rpath/SDL3.framework/Versions/A/SDL3",
|
||||
target_infos=[
|
||||
{
|
||||
"min_deployment": "10.13",
|
||||
"target": "arm64-macos",
|
||||
},
|
||||
{
|
||||
"min_deployment": "10.13",
|
||||
"target": "x86_64-macos",
|
||||
},
|
||||
]
|
||||
),
|
||||
TbdPlatform.IOS: TbdInfo(
|
||||
install_name="@rpath/SDL3.framework/SDL3",
|
||||
target_infos=[
|
||||
{
|
||||
"min_deployment": "11.0",
|
||||
"target": "arm64-ios",
|
||||
},
|
||||
{
|
||||
"min_deployment": "11.0",
|
||||
"target": "arm64-ios-simulator",
|
||||
},
|
||||
{
|
||||
"min_deployment": "11.0",
|
||||
"target": "x86_64-ios-simulator",
|
||||
},
|
||||
{
|
||||
"min_deployment": "11.0",
|
||||
"target": "arm64-tvos",
|
||||
},
|
||||
{
|
||||
"min_deployment": "11.0",
|
||||
"target": "arm64-tvos-simulator",
|
||||
},
|
||||
{
|
||||
"min_deployment": "11.0",
|
||||
"target": "x86_64-tvos-simulator",
|
||||
},
|
||||
{
|
||||
"min_deployment": "1.3",
|
||||
"target": "arm64-xros",
|
||||
},
|
||||
{
|
||||
"min_deployment": "1.3",
|
||||
"target": "arm64-xros-simulator",
|
||||
},
|
||||
]
|
||||
),
|
||||
}
|
||||
|
||||
def create_sdl3_tbd(symbols: list[str], tbd_info: TbdInfo):
|
||||
return {
|
||||
"main_library": {
|
||||
"compatibility_versions": [
|
||||
{
|
||||
"version": "201"
|
||||
}
|
||||
],
|
||||
"current_versions": [
|
||||
{
|
||||
"version": "201"
|
||||
}
|
||||
],
|
||||
"exported_symbols": [
|
||||
{
|
||||
"text": {
|
||||
"global": symbols
|
||||
}
|
||||
}
|
||||
],
|
||||
"flags": [
|
||||
{
|
||||
"attributes": [
|
||||
"not_app_extension_safe"
|
||||
]
|
||||
}
|
||||
],
|
||||
"install_names": [
|
||||
{
|
||||
"name": tbd_info.install_name
|
||||
}
|
||||
],
|
||||
"target_info": tbd_info.target_infos
|
||||
},
|
||||
"tapi_tbd_version": 5
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(allow_abbrev=False)
|
||||
parser.add_argument("--output", "-o", type=Path, help="Output path (default is stdout)")
|
||||
parser.add_argument("--platform", type=TbdPlatform, required=True,
|
||||
choices=[str(e) for e in TbdPlatform], help="Apple Platform")
|
||||
args = parser.parse_args()
|
||||
|
||||
with tempfile.NamedTemporaryFile() as f_temp:
|
||||
f_temp.close()
|
||||
subprocess.check_call([sys.executable,SDL_ROOT / "src/dynapi/gendynapi.py", "--dump", f_temp.name],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
with open(f_temp.name) as f_json:
|
||||
sdl3_json = json.load(f_json)
|
||||
|
||||
sdl3_macos_symbols = [f"_{symbol_info['name']}" for symbol_info in sdl3_json]
|
||||
sdl3_macos_symbols.sort()
|
||||
|
||||
tbd = create_sdl3_tbd(symbols=sdl3_macos_symbols, tbd_info=TBDINFOS[args.platform])
|
||||
with (args.output.open("w", newline="") if args.output else sys.stdout) as f_out:
|
||||
json.dump(tbd, fp=f_out, indent=2)
|
||||
f_out.write("\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -33,9 +33,9 @@
|
||||
#cmakedefine SDL_VENDOR_INFO "@SDL_VENDOR_INFO@"
|
||||
|
||||
#if defined(SDL_VENDOR_INFO)
|
||||
#define SDL_REVISION "@<@PROJECT_REVISION@>@ (" SDL_VENDOR_INFO ")"
|
||||
#define SDL_REVISION "SDL-@<@PROJECT_REVISION@>@ (" SDL_VENDOR_INFO ")"
|
||||
#else
|
||||
#define SDL_REVISION "@<@PROJECT_REVISION@>@"
|
||||
#define SDL_REVISION "SDL-@<@PROJECT_REVISION@>@"
|
||||
#endif
|
||||
|
||||
#endif /* SDL_revision_h_ */
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
*/
|
||||
#define SDL_REVISION "Some arbitrary string decided at SDL build time"
|
||||
#elif defined(SDL_VENDOR_INFO)
|
||||
#define SDL_REVISION "@<@PROJECT_REVISION@>@ (" SDL_VENDOR_INFO ")"
|
||||
#define SDL_REVISION "SDL-@<@PROJECT_REVISION@>@ (" SDL_VENDOR_INFO ")"
|
||||
#else
|
||||
#define SDL_REVISION "@<@PROJECT_REVISION@>@"
|
||||
#define SDL_REVISION "SDL-@<@PROJECT_REVISION@>@"
|
||||
#endif
|
||||
|
||||
#endif /* SDL_revision_h_ */
|
||||
|
||||
@@ -37,6 +37,11 @@ my $versionfname = 'include/SDL_version.h';
|
||||
my $versionmajorregex = '\A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z';
|
||||
my $versionminorregex = '\A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z';
|
||||
my $versionmicroregex = '\A\#define\s+SDL_MICRO_VERSION\s+(\d+)\Z';
|
||||
my $wikidocsectionsym = 'SDL_WIKI_DOCUMENTATION_SECTION';
|
||||
my $forceinlinesym = 'SDL_FORCE_INLINE';
|
||||
my $deprecatedsym = 'SDL_DEPRECATED';
|
||||
my $declspecsym = '(?:SDLMAIN_|SDL_)?DECLSPEC';
|
||||
my $callconvsym = 'SDLCALL';
|
||||
my $mainincludefname = 'SDL.h';
|
||||
my $selectheaderregex = '\ASDL.*?\.h\Z';
|
||||
my $projecturl = 'https://libsdl.org/';
|
||||
@@ -147,6 +152,12 @@ if (defined $optionsfname) {
|
||||
$envvardesc = $val, next if $key eq 'envvardesc';
|
||||
$envvarsymregex = $val, next if $key eq 'envvarsymregex';
|
||||
$envvarsymreplace = $val, next if $key eq 'envvarsymreplace';
|
||||
$wikidocsectionsym = $val, next if $key eq 'wikidocsectionsym';
|
||||
$forceinlinesym = $val, next if $key eq 'forceinlinesym';
|
||||
$deprecatedsym = $val, next if $key eq 'deprecatedsym';
|
||||
$declspecsym = $val, next if $key eq 'declspecsym';
|
||||
$callconvsym = $val, next if $key eq 'callconvsym';
|
||||
|
||||
}
|
||||
}
|
||||
close(OPTIONS);
|
||||
@@ -750,6 +761,7 @@ sub print_undocumented_section {
|
||||
}
|
||||
}
|
||||
|
||||
# !!! FIXME: generalize this for other libraries to use.
|
||||
sub strip_fn_declaration_metadata {
|
||||
my $decl = shift;
|
||||
$decl =~ s/SDL_(PRINTF|SCANF)_FORMAT_STRING\s*//; # don't want this metadata as part of the documentation.
|
||||
@@ -1153,7 +1165,7 @@ while (my $d = readdir(DH)) {
|
||||
} elsif ($ignoring_lines) {
|
||||
push @contents, $_;
|
||||
next;
|
||||
} elsif (/\A\s*\#\s*ifndef\s+SDL_WIKI_DOCUMENTATION_SECTION\s*\Z/) {
|
||||
} elsif (/\A\s*\#\s*ifndef\s+$wikidocsectionsym\s*\Z/) {
|
||||
$ignoring_lines = 1;
|
||||
push @contents, $_;
|
||||
next;
|
||||
@@ -1162,13 +1174,13 @@ while (my $d = readdir(DH)) {
|
||||
#print("CATEGORY FOR '$dent' CHANGED TO " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n");
|
||||
push @contents, $_;
|
||||
next;
|
||||
} elsif (/\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { # a function declaration without a doxygen comment?
|
||||
} elsif (/\A\s*extern\s+(?:$deprecatedsym\s+|)$declspecsym/) { # a function declaration without a doxygen comment?
|
||||
$symtype = 1; # function declaration
|
||||
@templines = ();
|
||||
$decl = $_;
|
||||
$str = '';
|
||||
$has_doxygen = 0;
|
||||
} elsif (/\A\s*SDL_FORCE_INLINE/) { # a (forced-inline) function declaration without a doxygen comment?
|
||||
} elsif (/\A\s*$forceinlinesym/) { # a (forced-inline) function declaration without a doxygen comment?
|
||||
$symtype = 1; # function declaration
|
||||
@templines = ();
|
||||
$decl = $_;
|
||||
@@ -1235,9 +1247,9 @@ while (my $d = readdir(DH)) {
|
||||
$lineno++ if defined $decl;
|
||||
$decl = '' if not defined $decl;
|
||||
chomp($decl);
|
||||
if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) {
|
||||
if ($decl =~ /\A\s*extern\s+(?:$deprecatedsym\s+|)$declspecsym/) {
|
||||
$symtype = 1; # function declaration
|
||||
} elsif ($decl =~ /\A\s*SDL_FORCE_INLINE/) {
|
||||
} elsif ($decl =~ /\A\s*$forceinlinesym/) {
|
||||
$symtype = 1; # (forced-inline) function declaration
|
||||
} elsif ($decl =~ /\A\s*\#\s*define\s+/) {
|
||||
$symtype = 2; # macro
|
||||
@@ -1274,7 +1286,7 @@ while (my $d = readdir(DH)) {
|
||||
}
|
||||
$headercategorydocs{$current_wiki_category} = $sym;
|
||||
} elsif ($symtype == 1) { # a function
|
||||
my $is_forced_inline = ($decl =~ /\A\s*SDL_FORCE_INLINE/);
|
||||
my $is_forced_inline = ($decl =~ /\A\s*$forceinlinesym/);
|
||||
|
||||
if ($is_forced_inline) {
|
||||
if (not $decl =~ /\)\s*(\{.*|)\s*\Z/) {
|
||||
@@ -1311,14 +1323,14 @@ while (my $d = readdir(DH)) {
|
||||
|
||||
my $paramsstr = undef;
|
||||
|
||||
if (!$is_forced_inline && $decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(\*?)\s*SDLCALL\s+(.*?)\s*\((.*?)\);/) {
|
||||
$sym = $8;
|
||||
$rettype = "$3$4$5$6";
|
||||
$paramsstr = $9;
|
||||
} elsif ($is_forced_inline && $decl =~ /\A\s*SDL_FORCE_INLINE\s+(SDL_DEPRECATED\s+|)(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(.*?)\s*\((.*?)\);/) {
|
||||
if (!$is_forced_inline && $decl =~ /\A\s*extern\s+(?:$deprecatedsym\s+|)$declspecsym\w*\s+(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(\*?)\s*$callconvsym\s+(.*?)\s*\((.*?)\);/) {
|
||||
$sym = $6;
|
||||
$rettype = "$2$3$4$5";
|
||||
$rettype = "$1$2$3$4$5";
|
||||
$paramsstr = $7;
|
||||
} elsif ($is_forced_inline && $decl =~ /\A\s*$forceinlinesym\s+(?:$deprecatedsym\s+|)(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(.*?)\s*\((.*?)\);/) {
|
||||
$sym = $5;
|
||||
$rettype = "$1$2$3$4";
|
||||
$paramsstr = $6;
|
||||
} else {
|
||||
#print "Found doxygen but no function sig:\n$str\n\n";
|
||||
foreach (@templines) {
|
||||
@@ -1384,7 +1396,7 @@ while (my $d = readdir(DH)) {
|
||||
|
||||
$decl = $_;
|
||||
$temp = $decl;
|
||||
$temp =~ s/\Aextern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(.*?)\s+(\*?)SDLCALL\s+/$3$4 /;
|
||||
$temp =~ s/\Aextern\s+(?:$deprecatedsym\s+|)$declspecsym\w*\s+(.*?)\s+(\*?)$callconvsym\s+/$1$2 /;
|
||||
$shrink_length = length($decl) - length($temp);
|
||||
$decl = $temp;
|
||||
} else {
|
||||
@@ -1449,7 +1461,7 @@ while (my $d = readdir(DH)) {
|
||||
}
|
||||
$decl .= $additional_decl;
|
||||
} elsif ($symtype == 2) { # a macro
|
||||
if ($decl =~ /\A\s*\#\s*define\s+(.*?)(\(.*?\)|)\s+/) {
|
||||
if ($decl =~ /\A\s*\#\s*define\s+(.*?)(\(.*?\)|)(\s+|\Z)/) {
|
||||
$sym = $1;
|
||||
} else {
|
||||
#print "Found doxygen but no macro:\n$str\n\n";
|
||||
@@ -2149,7 +2161,7 @@ if ($copy_direction == 1) { # --copy-to-headers
|
||||
opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n");
|
||||
while (readdir(DH)) {
|
||||
my $dent = $_;
|
||||
if ($dent =~ /\AREADME\-.*?\.md\Z/) { # we only bridge Markdown files here that start with "README-".
|
||||
if ($dent =~ /\A(README|INTRO)\-.*?\.md\Z/) { # we only bridge Markdown files here that start with "README-" or "INTRO-".
|
||||
filecopy("$wikipath/$dent", "$readmepath/$dent", "\n");
|
||||
}
|
||||
}
|
||||
@@ -2259,10 +2271,10 @@ if ($copy_direction == 1) { # --copy-to-headers
|
||||
|
||||
$desc =~ s/[\s\n]+\Z//ms;
|
||||
|
||||
if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful.
|
||||
if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) {
|
||||
print STDERR "WARNING: $sym\'s '\\param $arg' text starts with a capital letter: '$desc'. Fixing.\n";
|
||||
$desc = lcfirst($desc);
|
||||
if (0) {
|
||||
if (($desc =~ /\A[a-z]/) && (not $desc =~ /$apiprefixregex/)) {
|
||||
print STDERR "WARNING: $sym\'s '\\param $arg' text starts with a lowercase letter: '$desc'. Fixing.\n";
|
||||
$desc = ucfirst($desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2306,8 +2318,8 @@ if ($copy_direction == 1) { # --copy-to-headers
|
||||
}
|
||||
$desc =~ s/[\s\n]+\Z//ms;
|
||||
|
||||
if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful.
|
||||
if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) {
|
||||
if (0) {
|
||||
if (($desc =~ /\A[A-Z]/) && (not $desc =~ /$apiprefixregex/)) {
|
||||
print STDERR "WARNING: $sym\'s '\\returns' text starts with a capital letter: '$desc'. Fixing.\n";
|
||||
$desc = lcfirst($desc);
|
||||
}
|
||||
@@ -2451,7 +2463,7 @@ if ($copy_direction == 1) { # --copy-to-headers
|
||||
} else {
|
||||
die("Unexpected symbol type $symtype!");
|
||||
}
|
||||
my $str = "This $symtypename is available since SDL 3.0.0.";
|
||||
my $str = "This $symtypename is available since $projectshortname 3.0.0.";
|
||||
$sections{'Version'} = wordwrap(wikify($wikitype, $str)) . "\n";
|
||||
}
|
||||
}
|
||||
@@ -2762,7 +2774,7 @@ __EOF__
|
||||
opendir(DH, $readmepath) or die("Can't opendir '$readmepath': $!\n");
|
||||
while (my $d = readdir(DH)) {
|
||||
my $dent = $d;
|
||||
if ($dent =~ /\AREADME\-.*?\.md\Z/) { # we only bridge Markdown files here that start with "README-".
|
||||
if ($dent =~ /\A(README|INTRO)\-.*?\.md\Z/) { # we only bridge Markdown files here that start with "README-" or "INTRO".
|
||||
filecopy("$readmepath/$dent", "$wikipath/$dent", "\n");
|
||||
}
|
||||
}
|
||||
@@ -2772,7 +2784,7 @@ __EOF__
|
||||
opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n");
|
||||
while (my $d = readdir(DH)) {
|
||||
my $dent = $d;
|
||||
if ($dent =~ /\A(README\-.*?)\.md\Z/) {
|
||||
if ($dent =~ /\A((README|INTRO)\-.*?)\.md\Z/) {
|
||||
push @pages, $1;
|
||||
}
|
||||
}
|
||||
@@ -2916,7 +2928,7 @@ __EOF__
|
||||
$str .= ".\\\" Please report issues in this manpage's content at:\n";
|
||||
$str .= ".\\\" $bugreporturl\n";
|
||||
$str .= ".\\\" Please report issues in the generation of this manpage from the wiki at:\n";
|
||||
$str .= ".\\\" https://github.com/libsdl-org/SDL/issues/new?title=Misgenerated%20manpage%20for%20$sym\n";
|
||||
$str .= ".\\\" https://github.com/libsdl-org/SDL/issues/new?title=Misgenerated%20manpage%20for%20$sym\n"; # !!! FIXME: if this becomes a problem for other projects, we'll generalize this.
|
||||
$str .= ".\\\" $projectshortname can be found at $projecturl\n";
|
||||
|
||||
# Define a .URL macro. The "www.tmac" thing decides if we're using GNU roff (which has a .URL macro already), and if so, overrides the macro we just created.
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
set(LibUSB_PKG_CONFIG_SPEC libusb-1.0>=1.0.16)
|
||||
set(LibUSB_MIN_API_VERSION 0x01000102)
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_LibUSB ${LibUSB_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
|
||||
find_library(LibUSB_LIBRARY
|
||||
NAMES usb-1.0 libusb-1.0
|
||||
HINTS ${PC_LibUSB_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_path(LibUSB_INCLUDE_PATH
|
||||
NAMES libusb.h
|
||||
PATH_SUFFIXES libusb-1.0
|
||||
HINTS ${PC_LibUSB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(LibUSB_API_VERSION "LibUSB_API_VERSION-NOTFOUND")
|
||||
if(LibUSB_INCLUDE_PATH AND EXISTS "${LibUSB_INCLUDE_PATH}/libusb.h")
|
||||
file(READ "${LibUSB_INCLUDE_PATH}/libusb.h" LIBUSB_H_TEXT)
|
||||
if("${LIBUSB_H_TEXT}" MATCHES "#define[ \t]+LIBUSBX?_API_VERSION[ \t]+(0x[0-9a-fA-F]+)" )
|
||||
set(LibUSB_API_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LibUSB_API_VERSION)
|
||||
math(EXPR LibUSB_MIN_API_VERSION_decimal "${LibUSB_MIN_API_VERSION}")
|
||||
math(EXPR LibUSB_API_VERSION_decimal "${LibUSB_API_VERSION}")
|
||||
if(NOT LibUSB_MIN_API_VERSION_decimal LESS_EQUAL LibUSB_API_VERSION_decimal)
|
||||
set(LibUSB_LIBRARY "LibUSB_LIBRARY-NOTFOUND")
|
||||
endif()
|
||||
else()
|
||||
set(LibUSB_LIBRARY "LibUSB_LIBRARY-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(LibUSB_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of LibUSB")
|
||||
|
||||
set(LibUSB_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of LibUSB")
|
||||
|
||||
set(LibUSB_LINK_FLAGS "" CACHE STRING "Extra link flags of LibUSB")
|
||||
|
||||
if(LibUSB_LIBRARY AND LibUSB_INCLUDE_PATH)
|
||||
if(PC_LibUSB_FOUND)
|
||||
set(LibUSB_VERSION "${PC_LibUSB_VERSION}")
|
||||
else()
|
||||
set(LibUSB_VERSION "1.0.16-or-higher")
|
||||
endif()
|
||||
else()
|
||||
set(LibUSB_VERSION "LibUSB_VERSION-NOTFOUND")
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(LibUSB
|
||||
VERSION_VAR LibUSB_VERSION
|
||||
REQUIRED_VARS LibUSB_LIBRARY LibUSB_INCLUDE_PATH
|
||||
)
|
||||
|
||||
if(LibUSB_FOUND AND NOT TARGET LibUSB::LibUSB)
|
||||
add_library(LibUSB::LibUSB IMPORTED UNKNOWN)
|
||||
set_target_properties(LibUSB::LibUSB
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION "${LibUSB_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LibUSB_INCLUDE_PATH}"
|
||||
INTERFACE_COMPILE_OPTIONS "${LibUSB_COMPILE_OPTIONS}"
|
||||
INTERFACE_LINK_LIBRARIES "${LibUSB_LINK_LIBRARIES}"
|
||||
INTERFACE_LINK_OPTIONS "${LibUSB_LINK_OPTIONS}"
|
||||
)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
set(LibUSB_PKG_CONFIG_SPEC libusb-1.0>=1.0.16)
|
||||
set(LibUSB_MIN_API_VERSION 0x01000102)
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_LibUSB ${LibUSB_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
|
||||
find_library(LibUSB_LIBRARY
|
||||
NAMES usb-1.0 libusb-1.0 usb
|
||||
HINTS ${PC_LibUSB_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_path(LibUSB_INCLUDE_PATH
|
||||
NAMES libusb.h
|
||||
PATH_SUFFIXES libusb-1.0
|
||||
HINTS ${PC_LibUSB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(LibUSB_API_VERSION "LibUSB_API_VERSION-NOTFOUND")
|
||||
if(LibUSB_INCLUDE_PATH AND EXISTS "${LibUSB_INCLUDE_PATH}/libusb.h")
|
||||
file(READ "${LibUSB_INCLUDE_PATH}/libusb.h" LIBUSB_H_TEXT)
|
||||
if("${LIBUSB_H_TEXT}" MATCHES "#define[ \t]+LIBUSBX?_API_VERSION[ \t]+(0x[0-9a-fA-F]+)" )
|
||||
set(LibUSB_API_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LibUSB_API_VERSION)
|
||||
math(EXPR LibUSB_MIN_API_VERSION_decimal "${LibUSB_MIN_API_VERSION}")
|
||||
math(EXPR LibUSB_API_VERSION_decimal "${LibUSB_API_VERSION}")
|
||||
if(NOT LibUSB_MIN_API_VERSION_decimal LESS_EQUAL LibUSB_API_VERSION_decimal)
|
||||
set(LibUSB_LIBRARY "LibUSB_LIBRARY-NOTFOUND")
|
||||
endif()
|
||||
else()
|
||||
set(LibUSB_LIBRARY "LibUSB_LIBRARY-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(LibUSB_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of LibUSB")
|
||||
|
||||
set(LibUSB_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of LibUSB")
|
||||
|
||||
set(LibUSB_LINK_FLAGS "" CACHE STRING "Extra link flags of LibUSB")
|
||||
|
||||
if(LibUSB_LIBRARY AND LibUSB_INCLUDE_PATH)
|
||||
if(PC_LibUSB_FOUND)
|
||||
set(LibUSB_VERSION "${PC_LibUSB_VERSION}")
|
||||
else()
|
||||
set(LibUSB_VERSION "1.0.16-or-higher")
|
||||
endif()
|
||||
else()
|
||||
set(LibUSB_VERSION "LibUSB_VERSION-NOTFOUND")
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(LibUSB
|
||||
VERSION_VAR LibUSB_VERSION
|
||||
REQUIRED_VARS LibUSB_LIBRARY LibUSB_INCLUDE_PATH
|
||||
)
|
||||
|
||||
if(LibUSB_FOUND AND NOT TARGET LibUSB::LibUSB)
|
||||
add_library(LibUSB::LibUSB IMPORTED UNKNOWN)
|
||||
set_target_properties(LibUSB::LibUSB
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION "${LibUSB_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LibUSB_INCLUDE_PATH}"
|
||||
INTERFACE_COMPILE_OPTIONS "${LibUSB_COMPILE_OPTIONS}"
|
||||
INTERFACE_LINK_LIBRARIES "${LibUSB_LINK_LIBRARIES}"
|
||||
INTERFACE_LINK_OPTIONS "${LibUSB_LINK_OPTIONS}"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ if(EMSCRIPTEN)
|
||||
set(HAVE_O_CLOEXEC "1" CACHE INTERNAL "Test HAVE_O_CLOEXEC")
|
||||
set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR")
|
||||
set(COMPILER_SUPPORTS_GCC_ATOMICS "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_GCC_ATOMICS")
|
||||
set(LINKER_SUPPORTS_VERSION_SCRIPT "" CACHE INTERNAL "Test LINKER_SUPPORTS_VERSION_SCRIPT")
|
||||
set(HAVE_WL_VERSION_SCRIPT "" CACHE INTERNAL "Test HAVE_WL_VERSION_SCRIPT")
|
||||
set(LINKER_SUPPORTS_WL_NO_UNDEFINED "" CACHE INTERNAL "Test LINKER_SUPPORTS_WL_NO_UNDEFINED")
|
||||
set(ICONV_IN_LIBC "1" CACHE INTERNAL "Test ICONV_IN_LIBC")
|
||||
set(ICONV_IN_LIBICONV "" CACHE INTERNAL "Test ICONV_IN_LIBICONV")
|
||||
@@ -175,5 +175,11 @@ if(EMSCRIPTEN)
|
||||
set(HAVE_MEMFD_CREATE "" CACHE INTERNAL "Have symbol memfd_create")
|
||||
set(HAVE_POSIX_FALLOCATE "1" CACHE INTERNAL "Have symbol posix_fallocate")
|
||||
set(HAVE_DLOPEN_IN_LIBC "1" CACHE INTERNAL "Have symbol dlopen")
|
||||
set(HAVE_FDATASYNC "1" CACHE INTERNAL "Have symbol fdatasync")
|
||||
set(HAVE_GETHOSTNAME "1" CACHE INTERNAL "Have symbol gethostname")
|
||||
set(HAVE_SIGTIMEDWAIT "1" CACHE INTERNAL "Have symbol sigtimedwait")
|
||||
set(HAVE_PPOLL "" CACHE INTERNAL "Have symbol ppoll")
|
||||
set(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR "" CACHE INTERNAL "Have symbol posix_spawn_file_actions_addchdir")
|
||||
set(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP "1" CACHE INTERNAL "Have symbol posix_spawn_file_actions_addchdir_np")
|
||||
endfunction()
|
||||
endif()
|
||||
|
||||
@@ -155,7 +155,7 @@ if(NGAGESDK)
|
||||
#set(HAVE_O_CLOEXEC "" CACHE INTERNAL "Test HAVE_O_CLOEXEC")
|
||||
#set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR "" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR")
|
||||
set(COMPILER_SUPPORTS_GCC_ATOMICS "" CACHE INTERNAL "Test COMPILER_SUPPORTS_GCC_ATOMICS")
|
||||
set(LINKER_SUPPORTS_VERSION_SCRIPT "" CACHE INTERNAL "Test LINKER_SUPPORTS_VERSION_SCRIPT")
|
||||
set(HAVE_WL_VERSION_SCRIPT "" CACHE INTERNAL "Test HAVE_WL_VERSION_SCRIPT")
|
||||
set(LINKER_SUPPORTS_WL_NO_UNDEFINED "" CACHE INTERNAL "Test LINKER_SUPPORTS_WL_NO_UNDEFINED")
|
||||
set(ICONV_IN_LIBC "" CACHE INTERNAL "Test ICONV_IN_LIBC")
|
||||
set(ICONV_IN_LIBICONV "" CACHE INTERNAL "Test ICONV_IN_LIBICONV")
|
||||
|
||||
@@ -296,15 +296,15 @@ endfunction()
|
||||
function(check_linker_supports_version_file VAR)
|
||||
SDL_detect_linker()
|
||||
if(CMAKE_C_COMPILER_LINKER_ID MATCHES "^(MSVC)$")
|
||||
set(LINKER_SUPPORTS_VERSION_SCRIPT FALSE)
|
||||
set(${VAR} FALSE)
|
||||
else()
|
||||
cmake_push_check_state(RESET)
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n")
|
||||
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/dummy.sym")
|
||||
check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option)")
|
||||
check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" ${VAR} FAIL_REGEX "(unsupported|syntax error|unrecognized option)")
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
set(${VAR} "${LINKER_SUPPORTS_VERSION_SCRIPT}" PARENT_SCOPE)
|
||||
set(${VAR} "${${VAR}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 3.18)
|
||||
@@ -399,6 +399,7 @@ function(SDL_PrintSummary)
|
||||
PrintEnabledBackends("GPU drivers" "^SDL_GPU_([A-Z0-9]*)$")
|
||||
PrintEnabledBackends("Audio drivers" "^SDL_AUDIO_DRIVER_([A-Z0-9]*)$")
|
||||
PrintEnabledBackends("Joystick drivers" "^SDL_JOYSTICK_([A-Z0-9]*)$")
|
||||
PrintEnabledBackends("Camera drivers" "^SDL_CAMERA_DRIVER_([A-Z0-9]*)$")
|
||||
message(STATUS "")
|
||||
|
||||
if(UNIX)
|
||||
@@ -417,7 +418,7 @@ function(SDL_PrintSummary)
|
||||
"Most likely, this is not wanted."
|
||||
"\n"
|
||||
"On Linux, install the packages listed at "
|
||||
"https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md#build-dependencies "
|
||||
"https://wiki.libsdl.org/SDL3/README-linux#build-dependencies "
|
||||
"\n"
|
||||
"If you really don't need desktop windows, the documentation tells you how to skip this check. "
|
||||
"https://github.com/libsdl-org/SDL/blob/main/docs/README-cmake.md#cmake-fails-to-build-without-x11-or-wayland-support\n"
|
||||
@@ -427,6 +428,22 @@ function(SDL_PrintSummary)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(SDL_missing_dependency NAME OPTION)
|
||||
if(LINUX)
|
||||
message( FATAL_ERROR
|
||||
"Couldn't find dependency package for ${NAME}. Please install the needed packages or configure with -D${OPTION}=OFF"
|
||||
"\n"
|
||||
"The full set of dependencies is available at "
|
||||
"https://wiki.libsdl.org/SDL3/README-linux#build-dependencies "
|
||||
"\n"
|
||||
)
|
||||
else()
|
||||
message( FATAL_ERROR
|
||||
"Couldn't find dependency package for ${NAME}. Please install the needed packages or configure with -D${OPTION}=OFF"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(SDL_install_pdb TARGET DIRECTORY)
|
||||
get_property(type TARGET ${TARGET} PROPERTY TYPE)
|
||||
if(type MATCHES "^(SHARED_LIBRARY|EXECUTABLE)$")
|
||||
|
||||
@@ -392,72 +392,83 @@ macro(CheckX11)
|
||||
|
||||
check_include_file("X11/XKBlib.h" SDL_VIDEO_DRIVER_X11_HAS_XKBLIB)
|
||||
|
||||
if(SDL_X11_XCURSOR AND HAVE_XCURSOR_H AND XCURSOR_LIB)
|
||||
set(HAVE_X11_XCURSOR TRUE)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR "\"${XCURSOR_LIB_SONAME}\"")
|
||||
if(SDL_X11_XCURSOR)
|
||||
if (HAVE_XCURSOR_H AND XCURSOR_LIB)
|
||||
set(HAVE_X11_XCURSOR TRUE)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR "\"${XCURSOR_LIB_SONAME}\"")
|
||||
else()
|
||||
sdl_link_dependency(xcursor LIBS X11::Xcursor CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xcursor_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XCURSOR 1)
|
||||
else()
|
||||
sdl_link_dependency(xcursor LIBS X11::Xcursor CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xcursor_PKG_CONFIG_SPEC})
|
||||
SDL_missing_dependency(XCURSOR, SDL_X11_XCURSOR)
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XCURSOR 1)
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XDBE AND HAVE_XDBE_H)
|
||||
set(HAVE_X11_XDBE TRUE)
|
||||
set(SDL_VIDEO_DRIVER_X11_XDBE 1)
|
||||
if(SDL_X11_XDBE)
|
||||
if(HAVE_XDBE_H)
|
||||
set(HAVE_X11_XDBE TRUE)
|
||||
set(SDL_VIDEO_DRIVER_X11_XDBE 1)
|
||||
else()
|
||||
SDL_missing_dependency(XDBE, SDL_X11_XDBE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XINPUT AND HAVE_XINPUT2_H AND XI_LIB)
|
||||
set(HAVE_X11_XINPUT TRUE)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "\"${XI_LIB_SONAME}\"")
|
||||
if(SDL_X11_XINPUT)
|
||||
if(HAVE_XINPUT2_H AND XI_LIB)
|
||||
set(HAVE_X11_XINPUT TRUE)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "\"${XI_LIB_SONAME}\"")
|
||||
else()
|
||||
sdl_link_dependency(xi LIBS X11::Xi CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xi_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2 1)
|
||||
|
||||
# Check for scroll info
|
||||
check_c_source_compiles("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
XIScrollClassInfo *s;
|
||||
int main(int argc, char **argv) {}" HAVE_XINPUT2_SCROLLINFO)
|
||||
if(HAVE_XINPUT2_SCROLLINFO)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO 1)
|
||||
endif()
|
||||
|
||||
# Check for multitouch
|
||||
check_c_source_compiles_static("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
int event_type = XI_TouchBegin;
|
||||
XITouchClassInfo *t;
|
||||
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
|
||||
return (Status)0;
|
||||
}
|
||||
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_MULTITOUCH)
|
||||
if(HAVE_XINPUT2_MULTITOUCH)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1)
|
||||
endif()
|
||||
|
||||
# Check for gesture
|
||||
check_c_source_compiles("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
int event_type = XI_GesturePinchBegin;
|
||||
XITouchClassInfo *t;
|
||||
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
|
||||
return (Status)0;
|
||||
}
|
||||
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_GESTURE)
|
||||
if(HAVE_XINPUT2_GESTURE)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE 1)
|
||||
endif()
|
||||
|
||||
else()
|
||||
sdl_link_dependency(xi LIBS X11::Xi CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xi_PKG_CONFIG_SPEC})
|
||||
SDL_missing_dependency(XINPUT, SDL_X11_XINPUT)
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2 1)
|
||||
|
||||
# Check for scroll info
|
||||
check_c_source_compiles("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
XIScrollClassInfo *s;
|
||||
int main(int argc, char **argv) {}" HAVE_XINPUT2_SCROLLINFO)
|
||||
if(HAVE_XINPUT2_SCROLLINFO)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO 1)
|
||||
endif()
|
||||
|
||||
# Check for multitouch
|
||||
check_c_source_compiles_static("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
int event_type = XI_TouchBegin;
|
||||
XITouchClassInfo *t;
|
||||
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
|
||||
return (Status)0;
|
||||
}
|
||||
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_MULTITOUCH)
|
||||
if(HAVE_XINPUT2_MULTITOUCH)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1)
|
||||
endif()
|
||||
|
||||
# Check for gesture
|
||||
check_c_source_compiles("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
int event_type = XI_GesturePinchBegin;
|
||||
XITouchClassInfo *t;
|
||||
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
|
||||
return (Status)0;
|
||||
}
|
||||
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_GESTURE)
|
||||
if(HAVE_XINPUT2_GESTURE)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE 1)
|
||||
endif()
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
# check along with XInput2.h because we use Xfixes with XIBarrierReleasePointer
|
||||
@@ -470,54 +481,78 @@ macro(CheckX11)
|
||||
BarrierEventID b;
|
||||
int main(int argc, char **argv) { return 0; }" HAVE_XFIXES_H)
|
||||
endif()
|
||||
if(SDL_X11_XFIXES AND HAVE_XFIXES_H AND HAVE_XINPUT2_H AND XFIXES_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES "\"${XFIXES_LIB_SONAME}\"")
|
||||
if(SDL_X11_XFIXES)
|
||||
if (HAVE_XFIXES_H AND HAVE_XINPUT2_H AND XFIXES_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES "\"${XFIXES_LIB_SONAME}\"")
|
||||
else()
|
||||
sdl_link_dependency(xfixes LIBS X11::Xfixes CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xfixes_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XFIXES 1)
|
||||
set(HAVE_X11_XFIXES TRUE)
|
||||
else()
|
||||
sdl_link_dependency(xfixes LIBS X11::Xfixes CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xfixes_PKG_CONFIG_SPEC})
|
||||
SDL_missing_dependency(XFIXES, SDL_X11_XFIXES)
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XFIXES 1)
|
||||
set(HAVE_X11_XFIXES TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XSYNC AND HAVE_XSYNC_H AND XEXT_LIB)
|
||||
set(SDL_VIDEO_DRIVER_X11_XSYNC 1)
|
||||
set(HAVE_X11_XSYNC TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XRANDR AND HAVE_XRANDR_H AND XRANDR_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "\"${XRANDR_LIB_SONAME}\"")
|
||||
if(SDL_X11_XSYNC)
|
||||
if(HAVE_XSYNC_H AND XEXT_LIB)
|
||||
set(SDL_VIDEO_DRIVER_X11_XSYNC 1)
|
||||
set(HAVE_X11_XSYNC TRUE)
|
||||
else()
|
||||
sdl_link_dependency(xrandr LIBS X11::Xrandr CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xrandr_PKG_CONFIG_SPEC})
|
||||
SDL_missing_dependency(XSYNC, SDL_X11_XSYNC)
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XRANDR 1)
|
||||
set(HAVE_X11_XRANDR TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XSCRNSAVER AND HAVE_XSS_H AND XSS_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "\"${XSS_LIB_SONAME}\"")
|
||||
if(SDL_X11_XRANDR)
|
||||
if(HAVE_XRANDR_H AND XRANDR_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "\"${XRANDR_LIB_SONAME}\"")
|
||||
else()
|
||||
sdl_link_dependency(xrandr LIBS X11::Xrandr CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xrandr_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XRANDR 1)
|
||||
set(HAVE_X11_XRANDR TRUE)
|
||||
else()
|
||||
sdl_link_dependency(xss LIBS X11::Xss CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xss_PKG_CONFIG_SPEC})
|
||||
SDL_missing_dependency(XRANDR, SDL_X11_XRANDR)
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1)
|
||||
set(HAVE_X11_XSCRNSAVER TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XSHAPE AND HAVE_XSHAPE_H)
|
||||
set(SDL_VIDEO_DRIVER_X11_XSHAPE 1)
|
||||
set(HAVE_X11_XSHAPE TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XTEST AND HAVE_XTEST_H AND XTST_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XTEST "\"${XTST_LIB_SONAME}\"")
|
||||
if(SDL_X11_XSCRNSAVER)
|
||||
if(HAVE_XSS_H AND XSS_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "\"${XSS_LIB_SONAME}\"")
|
||||
else()
|
||||
sdl_link_dependency(xss LIBS X11::Xss CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xss_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1)
|
||||
set(HAVE_X11_XSCRNSAVER TRUE)
|
||||
else()
|
||||
sdl_link_dependency(xtst LIBS X11::Xtst CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xtst_PKG_CONFIG_SPEC})
|
||||
SDL_missing_dependency(XSCRNSAVER, SDL_X11_XSCRNSAVER)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XSHAPE)
|
||||
if(HAVE_XSHAPE_H)
|
||||
set(SDL_VIDEO_DRIVER_X11_XSHAPE 1)
|
||||
set(HAVE_X11_XSHAPE TRUE)
|
||||
else()
|
||||
SDL_missing_dependency(XSHAPE, SDL_X11_XSHAPE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SDL_X11_XTEST)
|
||||
if(HAVE_XTEST_H AND XTST_LIB)
|
||||
if(HAVE_X11_SHARED)
|
||||
set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XTEST "\"${XTST_LIB_SONAME}\"")
|
||||
else()
|
||||
sdl_link_dependency(xtst LIBS X11::Xtst CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xtst_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XTEST 1)
|
||||
set(HAVE_X11_XTEST TRUE)
|
||||
else()
|
||||
SDL_missing_dependency(XTEST SDL_X11_XTEST)
|
||||
endif()
|
||||
set(SDL_VIDEO_DRIVER_X11_XTEST 1)
|
||||
set(HAVE_X11_XTEST TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -553,6 +588,31 @@ macro(CheckFribidi)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(CheckLibThai)
|
||||
if(SDL_LIBTHAI)
|
||||
set(LIBTHAI_PKG_CONFIG_SPEC libthai)
|
||||
set(PC_LIBTHAI_FOUND FALSE)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_LIBTHAI IMPORTED_TARGET ${LIBTHAI_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
if(PC_LIBTHAI_FOUND)
|
||||
set(HAVE_LIBTHAI TRUE)
|
||||
set(HAVE_LIBTHAI_H 1)
|
||||
if(SDL_LIBTHAI_SHARED AND NOT HAVE_SDL_LOADSO)
|
||||
message(WARNING "You must have SDL_LoadObject() support for dynamic libthai loading")
|
||||
endif()
|
||||
FindLibraryAndSONAME("thai" LIBDIRS ${PC_LIBTHAI_LIBRARY_DIRS})
|
||||
if(SDL_LIBTHAI_SHARED AND THAI_LIB AND HAVE_SDL_LOADSO)
|
||||
set(SDL_LIBTHAI_DYNAMIC "\"${THAI_LIB_SONAME}\"")
|
||||
set(HAVE_LIBTHAI_SHARED TRUE)
|
||||
sdl_include_directories(PRIVATE SYSTEM $<TARGET_PROPERTY:PkgConfig::PC_LIBTHAI,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
else()
|
||||
sdl_link_dependency(libthai LIBS PkgConfig::PC_LIBTHAI PKG_CONFIG_PREFIX PC_LIBTHAI PKG_CONFIG_SPECS ${LIBTHAI_PKG_CONFIG_SPEC})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL)
|
||||
set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
|
||||
set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")
|
||||
@@ -765,13 +825,29 @@ macro(CheckOpenVR)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Requires
|
||||
# - N/A
|
||||
macro(FindOpenGLHeaders)
|
||||
find_package(OpenGL MODULE)
|
||||
# OPENGL_INCLUDE_DIRS is preferred over OPENGL_INCLUDE_DIR, but was only added in 3.29,
|
||||
# If the CMake minimum version is changed to be >= 3.29, the second check should be removed.
|
||||
if(OPENGL_INCLUDE_DIRS)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENGL_INCLUDE_DIRS})
|
||||
elseif(OPENGL_INCLUDE_DIR)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENGL_INCLUDE_DIR})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Requires:
|
||||
# - nada
|
||||
macro(CheckGLX)
|
||||
if(SDL_OPENGL)
|
||||
cmake_push_check_state()
|
||||
FindOpenGLHeaders()
|
||||
check_c_source_compiles("
|
||||
#include <GL/glx.h>
|
||||
int main(int argc, char** argv) { return 0; }" HAVE_OPENGL_GLX)
|
||||
cmake_pop_check_state()
|
||||
if(HAVE_OPENGL_GLX AND NOT HAVE_ROCKCHIP)
|
||||
set(SDL_VIDEO_OPENGL_GLX 1)
|
||||
endif()
|
||||
@@ -805,10 +881,13 @@ endmacro()
|
||||
# - nada
|
||||
macro(CheckOpenGL)
|
||||
if(SDL_OPENGL)
|
||||
cmake_push_check_state()
|
||||
FindOpenGLHeaders()
|
||||
check_c_source_compiles("
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
int main(int argc, char** argv) { return 0; }" HAVE_OPENGL)
|
||||
cmake_pop_check_state()
|
||||
if(HAVE_OPENGL)
|
||||
set(SDL_VIDEO_OPENGL 1)
|
||||
set(SDL_VIDEO_RENDER_OGL 1)
|
||||
@@ -821,6 +900,7 @@ endmacro()
|
||||
macro(CheckOpenGLES)
|
||||
if(SDL_OPENGLES)
|
||||
cmake_push_check_state()
|
||||
FindOpenGLHeaders()
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${SDL3_SOURCE_DIR}/src/video/khronos")
|
||||
check_c_source_compiles("
|
||||
#include <GLES/gl.h>
|
||||
|
||||
@@ -3,6 +3,7 @@ macro(SDL_DetectCompiler)
|
||||
set(USE_GCC FALSE)
|
||||
set(USE_INTELCC FALSE)
|
||||
set(USE_QCC FALSE)
|
||||
set(USE_TCC FALSE)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang|IntelLLVM")
|
||||
set(USE_CLANG TRUE)
|
||||
# Visual Studio 2019 v16.2 added support for Clang/LLVM.
|
||||
@@ -16,6 +17,8 @@ macro(SDL_DetectCompiler)
|
||||
set(USE_INTELCC TRUE)
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "QCC")
|
||||
set(USE_QCC TRUE)
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "TinyCC")
|
||||
set(USE_TCC TRUE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -39,7 +42,7 @@ function(SDL_AddCommonCompilerFlags TARGET)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC)
|
||||
if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC OR USE_TCC)
|
||||
if(MINGW)
|
||||
# See if GCC's -gdwarf-4 is supported
|
||||
# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101377 for why this is needed on Windows
|
||||
@@ -159,6 +162,10 @@ function(SDL_AddCommonCompilerFlags TARGET)
|
||||
sdl_target_compile_option_all_languages(${TARGET} "-fdiagnostics-color=always")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_TCC)
|
||||
sdl_target_compile_option_all_languages(${TARGET} "-DSTBI_NO_SIMD")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(check_x86_source_compiles BODY VAR)
|
||||
|
||||
@@ -22,7 +22,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIGURATION>")
|
||||
# This assumes the SDL source is available in vendored/SDL
|
||||
add_subdirectory(vendored/SDL EXCLUDE_FROM_ALL)
|
||||
|
||||
# on Web targets, we need CMake to generate a HTML webpage.
|
||||
# on Web targets, we need CMake to generate a HTML webpage.
|
||||
if(EMSCRIPTEN)
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".html" CACHE INTERNAL "")
|
||||
endif()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Introduction to SDL with MinGW
|
||||
|
||||
Without getting deep into the history, MinGW is a long running project that aims to bring gcc to Windows. That said, there's many distributions, versions, and forks floating around. We recommend installing [MSYS2](https://www.msys2.org/), as it's the easiest way to get a modern toolchain with a package manager to help with dependency management. This would allow you to follow the MSYS2 section below.
|
||||
Without getting deep into the history, MinGW is a long running project that aims to bring gcc to Windows. That said, there's many distributions, versions, and forks floating around. We recommend installing [MSYS2](https://www.msys2.org/), as it's the easiest way to get a modern toolchain with a package manager to help with dependency management. This would allow you to follow the MSYS2 section below.
|
||||
|
||||
Otherwise you'll want to follow the "Other Distributions" section below.
|
||||
|
||||
@@ -89,7 +89,7 @@ This should print out which library directory we'll need to use when compiling,
|
||||
Now we should have everything needed to compile and run our program. You'll need to ensure to replace `<version>` with the version of the release of SDL3 you downloaded, as well as use the `<arch>` we learned in the previous section.
|
||||
|
||||
```sh
|
||||
gcc hello.c -o hello.exe -I SDL3-<version>/<arch>/include -L SDL3-<version>/<arch>/lib -lSDL3 -mwindows
|
||||
gcc hello.c -o hello.exe -I SDL3-<version>/<arch>/include -L SDL3-<version>/<arch>/lib -lSDL3 -mwindows
|
||||
cp SDL3-<version>/<arch>/bin/SDL3.dll SDL3.dll
|
||||
./hello.exe
|
||||
```
|
||||
|
||||
@@ -169,31 +169,33 @@ for several reasons, not the least of which being that no one likes when a
|
||||
random browser tab suddenly starts making noise and the user has to scramble
|
||||
to figure out which and silence it.
|
||||
|
||||
SDL will allow you to open the audio device for playback in this
|
||||
circumstance, and your audio callback will fire, but SDL will throw the audio
|
||||
data away until the user interacts with the page. This helps apps that depend
|
||||
on the audio callback to make progress, and also keeps audio playback in sync
|
||||
SDL will allow you to open the audio device for playback in this circumstance,
|
||||
and your audio streams will consume data, but SDL will throw the audio data
|
||||
away until the user interacts with the page. This helps apps that depend on
|
||||
the audio callback to make progress, and also keeps audio playback in sync
|
||||
once the app is finally allowed to make noise.
|
||||
|
||||
There are two reasonable ways to deal with the silence at the app level:
|
||||
if you are writing some sort of media player thing, where the user expects
|
||||
there to be a volume control when you mouseover the canvas, just default
|
||||
that control to a muted state; if the user clicks on the control to unmute
|
||||
it, on this first click, open the audio device. This allows the media to
|
||||
it, on this first click, adjust your app's volume appropriately, and SDL will
|
||||
also start actually feeding the data to the browser. This allows the media to
|
||||
play at start, and the user can reasonably opt-in to listening.
|
||||
|
||||
Many games do not have this sort of UI, and are more rigid about starting
|
||||
audio along with everything else at the start of the process. For these, your
|
||||
best bet is to write a little Javascript that puts up a "Click here to play!"
|
||||
UI, and upon the user clicking, remove that UI and then call the Emscripten
|
||||
app's main() function. As far as the application knows, the audio device was
|
||||
available to be opened as soon as the program started, and since this magic
|
||||
happens in a little Javascript, you don't have to change your C/C++ code at
|
||||
all to make it happen.
|
||||
Many games do not have this sort of UI. For these, your best bet might be to
|
||||
write a little Javascript that puts up a "Click here to play!" UI, and upon
|
||||
the user clicking, remove that UI and then call the Emscripten app's main()
|
||||
function. As far as the application knows, audio was able to play as soon as
|
||||
the program started, and since this magic happens in a little Javascript, you
|
||||
don't have to change your C/C++ code at all to make it happen.
|
||||
|
||||
Please see the discussion at https://github.com/libsdl-org/SDL/issues/6385
|
||||
for some Javascript code to steal for this approach.
|
||||
|
||||
But if a game can just do without audio until the user clicks on the page,
|
||||
it will still operate correctly, as if the page was merely muted before then.
|
||||
|
||||
|
||||
## Rendering
|
||||
|
||||
@@ -226,9 +228,14 @@ most efficient, consistent, and correct way to run a game in a web browser.
|
||||
|
||||
## Building SDL/emscripten
|
||||
|
||||
Use the latest stable Emscripten release!
|
||||
|
||||
SDL currently requires at least Emscripten 3.16.0 to build. Newer versions
|
||||
are likely to work, as well.
|
||||
It's possible to build SDL with older Emscripten releases, such as 3.x, but
|
||||
several things will be silently broken, as bugs got fixed and web standards
|
||||
solidified over time. At the time of this writing, Emscripten 4.0.x is the
|
||||
current stable release. You're encouraged to install the latest stable release
|
||||
(`emsdk install latest ; emsdk activate latest` if using Emscripten's setup
|
||||
script), and make sure you're reasonably up to date as time goes on.
|
||||
|
||||
|
||||
Build:
|
||||
@@ -337,6 +344,22 @@ all has to live in memory at runtime.
|
||||
gives other options and details, and is worth a read.
|
||||
|
||||
|
||||
## Customizing index.html
|
||||
|
||||
You don't have to use the HTML that Emscripten produces; the above examples
|
||||
use `emcc -o index.html`, but you can `-o index.js` instead to just output
|
||||
code without an HTML page, and then provide your own. This is desirable for
|
||||
shipping products, even though the Emscripten-provided HTML is fine for
|
||||
prototyping. Certain things _must_ be in the HTML file or your program will
|
||||
not function correctly (or function at all). The specifics are beyond the
|
||||
scope of this document, but it's likely best to start with the Emscripten HTML
|
||||
and customize it, instead of starting from scratch.
|
||||
|
||||
The `<canvas>` element in the HTML _must not_ have a border or padding, or
|
||||
things will break in unexpected ways. This can be surprising when customizing
|
||||
the page's look. Plan accordingly.
|
||||
|
||||
|
||||
## Debugging
|
||||
|
||||
Debugging web apps is a mixed bag. You should compile and link with
|
||||
|
||||
@@ -19,7 +19,7 @@ Ubuntu 18.04, all available features enabled:
|
||||
libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
|
||||
libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
|
||||
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
|
||||
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev
|
||||
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev
|
||||
|
||||
Ubuntu 22.04+ can also add `libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev` to that command line.
|
||||
|
||||
@@ -28,11 +28,11 @@ Fedora 35, all available features enabled:
|
||||
sudo dnf install gcc git-core make cmake \
|
||||
alsa-lib-devel fribidi-devel pulseaudio-libs-devel pipewire-devel \
|
||||
libX11-devel libXext-devel libXrandr-devel libXcursor-devel libXfixes-devel \
|
||||
libXi-devel libXScrnSaver-devel dbus-devel ibus-devel \
|
||||
libXi-devel libXScrnSaver-devel libXtst-devel dbus-devel ibus-devel \
|
||||
systemd-devel mesa-libGL-devel libxkbcommon-devel mesa-libGLES-devel \
|
||||
mesa-libEGL-devel vulkan-devel wayland-devel wayland-protocols-devel \
|
||||
libdrm-devel mesa-libgbm-devel libusb1-devel libdecor-devel \
|
||||
pipewire-jack-audio-connection-kit-devel
|
||||
pipewire-jack-audio-connection-kit-devel libthai-devel
|
||||
|
||||
Fedora 39+ can also add `liburing-devel` to that command line.
|
||||
|
||||
@@ -44,11 +44,11 @@ openSUSE Tumbleweed:
|
||||
|
||||
sudo zypper in libunwind-devel libusb-1_0-devel Mesa-libGL-devel libxkbcommon-devel libdrm-devel \
|
||||
libgbm-devel pipewire-devel libpulse-devel sndio-devel Mesa-libEGL-devel alsa-devel xwayland-devel \
|
||||
wayland-devel wayland-protocols-devel
|
||||
wayland-devel wayland-protocols-devel libthai-devel fribidi-devel
|
||||
|
||||
Arch:
|
||||
|
||||
sudo pacman -S alsa-lib cmake hidapi ibus jack libdecor libgl libpulse libusb libx11 libxcursor libxext libxinerama libxkbcommon libxrandr libxrender libxss libxtst mesa ninja pipewire sndio vulkan-driver vulkan-headers wayland wayland-protocols
|
||||
sudo pacman -S alsa-lib cmake hidapi ibus jack libdecor libthai fribidi libgl libpulse libusb libx11 libxcursor libxext libxfixes libxi libxinerama libxkbcommon libxrandr libxrender libxss libxtst mesa ninja pipewire sndio vulkan-driver vulkan-headers wayland wayland-protocols
|
||||
|
||||
|
||||
Joystick does not work
|
||||
|
||||
@@ -206,6 +206,13 @@ The SDL_AppResult value that terminated the app is provided here, in case
|
||||
it's useful to know if this was a successful or failing run of the app.
|
||||
|
||||
|
||||
## Using main functions from other languages
|
||||
|
||||
If you're not using C/C++, using SDL's entry points is still possible but is
|
||||
more complex. Please refer to https://wiki.libsdl.org/SDL3/NonstandardStartup
|
||||
for the technical details.
|
||||
|
||||
|
||||
## Summary and Best Practices
|
||||
|
||||
- **Always Include SDL_main.h in One Source File:** When working with SDL,
|
||||
|
||||
@@ -265,7 +265,7 @@ static void draw(SDL_Renderer *renderer, const float (*edges)[6], const Player p
|
||||
SDL_RenderLine(renderer, hor_origin-10, ver_origin, hor_origin+10, ver_origin);
|
||||
}
|
||||
}
|
||||
SDL_SetRenderClipRect(renderer, 0);
|
||||
SDL_SetRenderClipRect(renderer, NULL);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
SDL_RenderDebugText(renderer, 0, 0, debug_string);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
@@ -77,8 +77,9 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
const float size = 30.0f;
|
||||
const float x = 320.0f;
|
||||
const float y = 95.0f - (size / 2.0f);
|
||||
const float r = (float) i * (SDL_PI_F / 180.0f);
|
||||
SDL_SetRenderDrawColor(renderer, SDL_rand(256), SDL_rand(256), SDL_rand(256), SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderLine(renderer, x, y, x + SDL_sinf((float) i) * size, y + SDL_cosf((float) i) * size);
|
||||
SDL_RenderLine(renderer, x, y, x + SDL_cosf(r) * size, y + SDL_sinf(r) * size);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main include header for the SDL library, version 3.3.2
|
||||
* Main include header for the SDL library, version 3.3.4
|
||||
*
|
||||
* It is almost always best to include just this one header instead of
|
||||
* picking out individual headers included here. There are exceptions to
|
||||
|
||||
@@ -136,7 +136,7 @@ extern "C" {
|
||||
#define SDL_TriggerBreakpoint() __builtin_debugtrap()
|
||||
#elif SDL_HAS_BUILTIN(__builtin_trap)
|
||||
#define SDL_TriggerBreakpoint() __builtin_trap()
|
||||
#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
#elif (defined(__GNUC__) || defined(__clang__) || defined(__TINYC__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
|
||||
#elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv)
|
||||
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" )
|
||||
@@ -176,7 +176,7 @@ extern "C" {
|
||||
# define SDL_FUNCTION "???"
|
||||
#endif
|
||||
|
||||
#ifndef SDL_FILE
|
||||
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||
|
||||
/**
|
||||
* A macro that reports the current file being compiled.
|
||||
@@ -184,16 +184,21 @@ extern "C" {
|
||||
* This macro is only defined if it isn't already defined, so to override it
|
||||
* (perhaps with something that doesn't provide path information at all, so
|
||||
* build machine information doesn't leak into public binaries), apps can
|
||||
* define this macro before including SDL_assert.h. For example, Clang and GCC
|
||||
* can define this to `FILE_NAME` to get just the source filename instead of
|
||||
* the full path.
|
||||
* define this macro before including SDL.h or SDL_assert.h.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_FILE __FILE_NAME__
|
||||
|
||||
#elif !defined(SDL_FILE)
|
||||
#ifdef __FILE_NAME__
|
||||
#define SDL_FILE __FILE_NAME__
|
||||
#else
|
||||
#define SDL_FILE __FILE__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SDL_ASSERT_FILE
|
||||
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||
|
||||
/**
|
||||
* A macro that reports the current file being compiled, for use in
|
||||
@@ -208,6 +213,9 @@ extern "C" {
|
||||
* \since This macro is available since SDL 3.4.0.
|
||||
*/
|
||||
#define SDL_ASSERT_FILE SDL_FILE
|
||||
|
||||
#elif !defined(SDL_ASSERT_FILE)
|
||||
#define SDL_ASSERT_FILE SDL_FILE
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1336,7 +1336,7 @@ extern SDL_DECLSPEC int * SDLCALL SDL_GetAudioStreamOutputChannelMap(SDL_AudioSt
|
||||
* \threadsafety It is safe to call this function from any thread, as it holds
|
||||
* a stream-specific mutex while running. Don't change the
|
||||
* stream's format to have a different number of channels from a
|
||||
* a different thread at the same time, though!
|
||||
* different thread at the same time, though!
|
||||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
*
|
||||
|
||||
@@ -140,11 +140,11 @@ typedef void (SDLCALL *SDL_DialogFileCallback)(void *userdata, const char * cons
|
||||
* \param window the window that the dialog should be modal for, may be NULL.
|
||||
* Not all platforms support this option.
|
||||
* \param filters a list of filters, may be NULL. See the
|
||||
* [`SDL_DialogFileFilter` documentation for
|
||||
* examples](SDL_DialogFileFilter#code-examples). Not all
|
||||
* platforms support this option, and platforms that do support
|
||||
* it may allow the user to ignore the filters. If non-NULL, it
|
||||
* must remain valid at least until the callback is invoked.
|
||||
* [`SDL_DialogFileFilter`](SDL_DialogFileFilter#code-examples)
|
||||
* documentation for examples]. Not all platforms support this
|
||||
* option, and platforms that do support it may allow the user
|
||||
* to ignore the filters. If non-NULL, it must remain valid at
|
||||
* least until the callback is invoked.
|
||||
* \param nfilters the number of filters. Ignored if filters is NULL.
|
||||
* \param default_location the default folder or file to start the dialog at,
|
||||
* may be NULL. Not all platforms support this option.
|
||||
|
||||
@@ -818,6 +818,9 @@ typedef struct SDL_PinchFingerEvent
|
||||
* is there." The pen touching and lifting off from the tablet while not
|
||||
* leaving the area are handled by SDL_EVENT_PEN_DOWN and SDL_EVENT_PEN_UP.
|
||||
*
|
||||
* Not all platforms have a window associated with the pen during proximity
|
||||
* events. Some wait until motion/button/etc events to offer this info.
|
||||
*
|
||||
* \since This struct is available since SDL 3.2.0.
|
||||
*/
|
||||
typedef struct SDL_PenProximityEvent
|
||||
@@ -1069,7 +1072,7 @@ typedef union SDL_Event
|
||||
} SDL_Event;
|
||||
|
||||
/* Make sure we haven't broken binary compatibility */
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof((SDL_static_cast(SDL_Event *, NULL))->padding));
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
@@ -77,6 +77,9 @@ extern "C" {
|
||||
* - `parent`: the containing directory of the bundle. For example:
|
||||
* `/Applications/SDLApp/`
|
||||
*
|
||||
* **Android Specific Functionality**: This function returns "./", which
|
||||
* allows filesystem operations to use internal storage and the asset system.
|
||||
*
|
||||
* **Nintendo 3DS Specific Functionality**: This function returns "romfs"
|
||||
* directory of the application as it is uncommon to store resources outside
|
||||
* the executable. As such it is not a writable directory.
|
||||
|
||||
@@ -2294,7 +2294,7 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice(
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN`: The app is able to
|
||||
* provide Metal shader libraries if applicable.
|
||||
*
|
||||
* With the D3D12 renderer:
|
||||
* With the D3D12 backend:
|
||||
*
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING`: the prefix to
|
||||
* use for all vertex semantics, default is "TEXCOORD".
|
||||
@@ -2307,6 +2307,20 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice(
|
||||
* either supports Tier 2 Resource Binding or does not support D3D12 in any
|
||||
* capacity. Defaults to false.
|
||||
*
|
||||
* With the Vulkan backend:
|
||||
*
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION_BOOLEAN`:
|
||||
* By default, Vulkan device enumeration includes drivers of all types,
|
||||
* including software renderers (for example, the Lavapipe Mesa driver).
|
||||
* This can be useful if your application _requires_ SDL_GPU, but if you can
|
||||
* provide your own fallback renderer (for example, an OpenGL renderer) this
|
||||
* property can be set to true. Defaults to false.
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER`: a pointer to an
|
||||
* SDL_GPUVulkanOptions structure to be processed during device creation.
|
||||
* This allows configuring a variety of Vulkan-specific options such as
|
||||
* increasing the API version and opting into extensions aside from the
|
||||
* minimal set SDL requires.
|
||||
*
|
||||
* \param props the properties to use.
|
||||
* \returns a GPU context on success or NULL on failure; call SDL_GetError()
|
||||
* for more information.
|
||||
@@ -2337,6 +2351,36 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN "SDL.gpu.device.create.d3d12.allowtier1resourcebinding"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION_BOOLEAN "SDL.gpu.device.create.vulkan.requirehardwareacceleration"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER "SDL.gpu.device.create.vulkan.options"
|
||||
|
||||
|
||||
/**
|
||||
* A structure specifying additional options when using Vulkan.
|
||||
*
|
||||
* When no such structure is provided, SDL will use Vulkan API version 1.0 and
|
||||
* a minimal set of features. The requested API version influences how the
|
||||
* feature_list is processed by SDL. When requesting API version 1.0, the
|
||||
* feature_list is ignored. Only the vulkan_10_phyisical_device_features and
|
||||
* the extension lists are used. When requesting API version 1.1, the
|
||||
* feature_list is scanned for feature structures introduced in Vulkan 1.1.
|
||||
* When requesting Vulkan 1.2 or higher, the feature_list is additionally
|
||||
* scanned for compound feature structs such as
|
||||
* VkPhysicalDeviceVulkan11Features. The device and instance extension lists,
|
||||
* as well as vulkan_10_physical_device_features, are always processed.
|
||||
*
|
||||
* \since This struct is available since SDL 3.4.0.
|
||||
*/
|
||||
typedef struct SDL_GPUVulkanOptions
|
||||
{
|
||||
Uint32 vulkan_api_version; /**< The Vulkan API version to request for the instance. Use Vulkan's VK_MAKE_VERSION or VK_MAKE_API_VERSION. */
|
||||
void *feature_list; /**< Pointer to the first element of a chain of Vulkan feature structs. (Requires API version 1.1 or higher.)*/
|
||||
void *vulkan_10_physical_device_features; /**< Pointer to a VkPhysicalDeviceFeatures struct to enable additional Vulkan 1.0 features. */
|
||||
Uint32 device_extension_count; /**< Number of additional device extensions to require. */
|
||||
const char **device_extension_names; /**< Pointer to a list of additional device extensions to require. */
|
||||
Uint32 instance_extension_count; /**< Number of additional instance extensions to require. */
|
||||
const char **instance_extension_names; /**< Pointer to a list of additional instance extensions to require. */
|
||||
} SDL_GPUVulkanOptions;
|
||||
|
||||
/**
|
||||
* Destroys a GPU context previously returned by SDL_CreateGPUDevice.
|
||||
@@ -2901,6 +2945,12 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetGPUTextureName(
|
||||
*
|
||||
* Useful for debugging.
|
||||
*
|
||||
* On Direct3D 12, using SDL_InsertGPUDebugLabel requires
|
||||
* WinPixEventRuntime.dll to be in your PATH or in the same directory as your
|
||||
* executable. See
|
||||
* [here](https://devblogs.microsoft.com/pix/winpixeventruntime/)
|
||||
* for instructions on how to obtain it.
|
||||
*
|
||||
* \param command_buffer a command buffer.
|
||||
* \param text a UTF-8 string constant to insert as the label.
|
||||
*
|
||||
@@ -2919,6 +2969,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_InsertGPUDebugLabel(
|
||||
* Each call to SDL_PushGPUDebugGroup must have a corresponding call to
|
||||
* SDL_PopGPUDebugGroup.
|
||||
*
|
||||
* On Direct3D 12, using SDL_PushGPUDebugGroup requires WinPixEventRuntime.dll
|
||||
* to be in your PATH or in the same directory as your executable. See
|
||||
* [here](https://devblogs.microsoft.com/pix/winpixeventruntime/)
|
||||
* for instructions on how to obtain it.
|
||||
*
|
||||
* On some backends (e.g. Metal), pushing a debug group during a
|
||||
* render/blit/compute pass will create a group that is scoped to the native
|
||||
* pass rather than the command buffer. For best results, if you push a debug
|
||||
@@ -2938,6 +2993,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUDebugGroup(
|
||||
/**
|
||||
* Ends the most-recently pushed debug group.
|
||||
*
|
||||
* On Direct3D 12, using SDL_PopGPUDebugGroup requires WinPixEventRuntime.dll
|
||||
* to be in your PATH or in the same directory as your executable. See
|
||||
* [here](https://devblogs.microsoft.com/pix/winpixeventruntime/)
|
||||
* for instructions on how to obtain it.
|
||||
*
|
||||
* \param command_buffer a command buffer.
|
||||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
|
||||
@@ -788,22 +788,26 @@ extern "C" {
|
||||
#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
|
||||
|
||||
/**
|
||||
* Dictate that newly-created windows will fill the whole browser window.
|
||||
* Dictate that windows on Emscripten will fill the whole browser window.
|
||||
*
|
||||
* The canvas element fills the entire document. Resize events will be
|
||||
* generated as the browser window is resized, as that will adjust the canvas
|
||||
* size as well. The canvas will cover anything else on the page, including
|
||||
* any controls provided by Emscripten in its generated HTML file. Often times
|
||||
* this is desirable for a browser-based game, but it means several things
|
||||
* that we expect of an SDL window on other platforms might not work as
|
||||
* expected, such as minimum window sizes and aspect ratios.
|
||||
* When enabled, the canvas element fills the entire document. Resize events
|
||||
* will be generated as the browser window is resized, as that will adjust the
|
||||
* canvas size as well. The canvas will cover anything else on the page,
|
||||
* including any controls provided by Emscripten in its generated HTML file
|
||||
* (in fact, any elements on the page that aren't the canvas will be moved
|
||||
* into a hidden `div` element).
|
||||
*
|
||||
* Often times this is desirable for a browser-based game, but it means
|
||||
* several things that we expect of an SDL window on other platforms might not
|
||||
* work as expected, such as minimum window sizes and aspect ratios.
|
||||
*
|
||||
* This hint overrides SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN
|
||||
* properties when creating an SDL window.
|
||||
*
|
||||
* This hint only applies to the emscripten platform.
|
||||
* This hint only applies to the Emscripten platform.
|
||||
*
|
||||
* This hint should be set before creating a window.
|
||||
* This hint can be set at any time (before creating the window, or to toggle
|
||||
* its state later). Only one window can fill the document at a time.
|
||||
*
|
||||
* \since This hint is available since SDL 3.4.0.
|
||||
*/
|
||||
@@ -2620,6 +2624,21 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_MAC_SCROLL_MOMENTUM "SDL_MAC_SCROLL_MOMENTUM"
|
||||
|
||||
/**
|
||||
* A variable controlling whether holding down a key will repeat the pressed
|
||||
* key or open the accents menu on macOS.
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
*
|
||||
* - "0": Holding a key will open the accents menu for that key.
|
||||
* - "1": Holding a key will repeat the pressed key. (default)
|
||||
*
|
||||
* This hint needs to be set before SDL_Init().
|
||||
*
|
||||
* \since This hint is available since SDL 3.4.0.
|
||||
*/
|
||||
#define SDL_HINT_MAC_PRESS_AND_HOLD "SDL_MAC_PRESS_AND_HOLD"
|
||||
|
||||
/**
|
||||
* Request SDL_AppIterate() be called at a specific rate.
|
||||
*
|
||||
@@ -4384,6 +4403,28 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD"
|
||||
|
||||
/**
|
||||
* A variable controlling whether or not the RIDEV_NOHOTKEYS flag is set when
|
||||
* enabling Windows raw keyboard events.
|
||||
*
|
||||
* This blocks any hotkeys that have been registered by applications from
|
||||
* having any effect beyond generating raw WM_INPUT events.
|
||||
*
|
||||
* This flag does not affect system-hotkeys like ALT-TAB or CTRL-ALT-DEL, but
|
||||
* does affect the Windows Logo key since it is a userland hotkey registered
|
||||
* by explorer.exe.
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
*
|
||||
* - "0": Hotkeys are not excluded. (default)
|
||||
* - "1": Hotkeys are excluded.
|
||||
*
|
||||
* This hint can be set anytime.
|
||||
*
|
||||
* \since This hint is available since SDL 3.4.0.
|
||||
*/
|
||||
#define SDL_HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS "SDL_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS"
|
||||
|
||||
/**
|
||||
* A variable controlling whether SDL uses Kernel Semaphores on Windows.
|
||||
*
|
||||
|
||||
@@ -268,6 +268,7 @@ _m_prefetch(void *__P)
|
||||
#endif /* compiler version */
|
||||
|
||||
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||
|
||||
/**
|
||||
* A macro to decide if the compiler supports `__attribute__((target))`.
|
||||
*
|
||||
@@ -280,12 +281,14 @@ _m_prefetch(void *__P)
|
||||
* \sa SDL_TARGETING
|
||||
*/
|
||||
#define SDL_HAS_TARGET_ATTRIBS
|
||||
|
||||
#elif defined(__loongarch64) && defined(__GNUC__) && (__GNUC__ >= 15)
|
||||
/* LoongArch requires GCC 15+ for target attribute support */
|
||||
# define SDL_HAS_TARGET_ATTRIBS
|
||||
#elif defined(__clang__) && defined(__has_attribute)
|
||||
# if __has_attribute(target)
|
||||
# define SDL_HAS_TARGET_ATTRIBS
|
||||
# endif
|
||||
#elif defined(__GNUC__) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */
|
||||
#elif defined(__GNUC__) && !defined(__loongarch64) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */
|
||||
# define SDL_HAS_TARGET_ATTRIBS
|
||||
#elif defined(__ICC) && __ICC >= 1600
|
||||
# define SDL_HAS_TARGET_ATTRIBS
|
||||
|
||||
@@ -45,11 +45,13 @@
|
||||
* `SDLK_*` constant for those keys that do not generate characters.
|
||||
*
|
||||
* A special exception is the number keys at the top of the keyboard which map
|
||||
* to SDLK_0...SDLK_9 on AZERTY layouts.
|
||||
* by default to SDLK_0...SDLK_9 on AZERTY layouts.
|
||||
*
|
||||
* Keys with the `SDLK_EXTENDED_MASK` bit set do not map to a scancode or
|
||||
* unicode code point.
|
||||
*
|
||||
* Many common keycodes are listed below, but this list is not exhaustive.
|
||||
*
|
||||
* \since This datatype is available since SDL 3.2.0.
|
||||
*
|
||||
* \sa SDL_HINT_KEYCODE_OPTIONS
|
||||
|
||||
@@ -110,7 +110,8 @@
|
||||
* Even if available, an app can define SDL_MAIN_HANDLED and provide their
|
||||
* own, if they know what they're doing.
|
||||
*
|
||||
* This macro is used internally by SDL, and apps probably shouldn't rely on it.
|
||||
* This macro is used internally by SDL, and apps probably shouldn't rely on
|
||||
* it.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
@@ -125,10 +126,11 @@
|
||||
* This macro is defined by `SDL_main.h`, which is not automatically included
|
||||
* by `SDL.h`.
|
||||
*
|
||||
* Even if required, an app can define SDL_MAIN_HANDLED and provide their
|
||||
* own, if they know what they're doing.
|
||||
* Even if required, an app can define SDL_MAIN_HANDLED and provide their own,
|
||||
* if they know what they're doing.
|
||||
*
|
||||
* This macro is used internally by SDL, and apps probably shouldn't rely on it.
|
||||
* This macro is used internally by SDL, and apps probably shouldn't rely on
|
||||
* it.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
@@ -165,12 +167,10 @@
|
||||
*/
|
||||
#define SDL_MAIN_NEEDED
|
||||
|
||||
#elif defined(SDL_PLATFORM_IOS)
|
||||
/* On iOS SDL provides a main function that creates an application delegate
|
||||
and starts the iOS application run loop.
|
||||
#elif defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS)
|
||||
/* On iOS and tvOS SDL provides a main function that creates an application delegate and starts the application run loop.
|
||||
|
||||
To use it, just #include SDL_main.h in the source file that contains your
|
||||
main() function.
|
||||
To use it, just #include <SDL3/SDL_main.h> in the source file that contains your main() function.
|
||||
|
||||
See src/video/uikit/SDL_uikitappdelegate.m for more details.
|
||||
*/
|
||||
@@ -553,6 +553,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetMainReady(void);
|
||||
* using SDL_main (like when using SDL_MAIN_HANDLED). When using this, you do
|
||||
* *not* need SDL_SetMainReady().
|
||||
*
|
||||
* If `argv` is NULL, SDL will provide command line arguments, either by
|
||||
* querying the OS for them if possible, or supplying a filler array if not.
|
||||
*
|
||||
* \param argc the argc parameter from the application's main() function, or 0
|
||||
* if the platform's main-equivalent has no argc.
|
||||
* \param argv the argv parameter from the application's main() function, or
|
||||
|
||||
@@ -37,12 +37,28 @@
|
||||
* - SDL_EVENT_PEN_BUTTON_DOWN, SDL_EVENT_PEN_BUTTON_UP (SDL_PenButtonEvent)
|
||||
* - SDL_EVENT_PEN_AXIS (SDL_PenAxisEvent)
|
||||
*
|
||||
* When a pen starts providing input, SDL will assign it a unique SDL_PenID,
|
||||
* which will remain for the life of the process, as long as the pen stays
|
||||
* connected.
|
||||
*
|
||||
* Pens may provide more than simple touch input; they might have other axes,
|
||||
* such as pressure, tilt, rotation, etc.
|
||||
*
|
||||
* When a pen starts providing input, SDL will assign it a unique SDL_PenID,
|
||||
* which will remain for the life of the process, as long as the pen stays
|
||||
* connected. A pen leaving proximity (being taken far enough away from the
|
||||
* digitizer tablet that it no longer reponds) and then coming back should
|
||||
* fire proximity events, but the SDL_PenID should remain consistent.
|
||||
* Unplugging the digitizer and reconnecting may cause future input to have a
|
||||
* new SDL_PenID, as SDL may not know that this is the same hardware.
|
||||
*
|
||||
* Please note that various platforms vary wildly in how (and how well) they
|
||||
* support pen input. If your pen supports some piece of functionality but SDL
|
||||
* doesn't seem to, it might actually be the operating system's fault. For
|
||||
* example, some platforms can manage multiple devices at the same time, but
|
||||
* others will make any connected pens look like a single logical device, much
|
||||
* how all USB mice connected to a computer will move the same system cursor.
|
||||
* cursor. Other platforms might not support pen buttons, or the distance
|
||||
* axis, etc. Very few platforms can even report _what_ functionality the pen
|
||||
* supports in the first place, so best practices is to either build UI to let
|
||||
* the user configure their pens, or be prepared to handle new functionality
|
||||
* for a pen the first time an event is reported.
|
||||
*/
|
||||
|
||||
#ifndef SDL_pen_h_
|
||||
@@ -65,7 +81,12 @@ extern "C" {
|
||||
*
|
||||
* These show up in pen events when SDL sees input from them. They remain
|
||||
* consistent as long as SDL can recognize a tool to be the same pen; but if a
|
||||
* pen physically leaves the area and returns, it might get a new ID.
|
||||
* pen's digitizer table is physically detached from the computer, it might
|
||||
* get a new ID when reconnected, as SDL won't know it's the same device.
|
||||
*
|
||||
* These IDs are only stable within a single run of a program; the next time a
|
||||
* program is run, the pen's ID will likely be different, even if the hardware
|
||||
* hasn't been disconnected, etc.
|
||||
*
|
||||
* \since This datatype is available since SDL 3.2.0.
|
||||
*/
|
||||
@@ -92,13 +113,14 @@ typedef Uint32 SDL_PenID;
|
||||
*/
|
||||
typedef Uint32 SDL_PenInputFlags;
|
||||
|
||||
#define SDL_PEN_INPUT_DOWN (1u << 0) /**< pen is pressed down */
|
||||
#define SDL_PEN_INPUT_BUTTON_1 (1u << 1) /**< button 1 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_2 (1u << 2) /**< button 2 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_3 (1u << 3) /**< button 3 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_4 (1u << 4) /**< button 4 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_5 (1u << 5) /**< button 5 is pressed */
|
||||
#define SDL_PEN_INPUT_ERASER_TIP (1u << 30) /**< eraser tip is used */
|
||||
#define SDL_PEN_INPUT_DOWN (1u << 0) /**< pen is pressed down */
|
||||
#define SDL_PEN_INPUT_BUTTON_1 (1u << 1) /**< button 1 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_2 (1u << 2) /**< button 2 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_3 (1u << 3) /**< button 3 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_4 (1u << 4) /**< button 4 is pressed */
|
||||
#define SDL_PEN_INPUT_BUTTON_5 (1u << 5) /**< button 5 is pressed */
|
||||
#define SDL_PEN_INPUT_ERASER_TIP (1u << 30) /**< eraser tip is used */
|
||||
#define SDL_PEN_INPUT_IN_PROXIMITY (1u << 31) /**< pen is in proximity (since SDL 3.4.0) */
|
||||
|
||||
/**
|
||||
* Pen axis indices.
|
||||
|
||||
@@ -451,7 +451,7 @@ typedef enum SDL_PackedLayout
|
||||
* expressions with side-effects here.
|
||||
*
|
||||
* \param format an SDL_PixelFormat to check.
|
||||
* \returns true if the format is 10-bit, false otherwise.
|
||||
* \returns true if the format is a floating point, false otherwise.
|
||||
*
|
||||
* \threadsafety It is safe to call this macro from any thread.
|
||||
*
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
#if TARGET_OS_VISION
|
||||
|
||||
/**
|
||||
* A preprocessor macro that is only defined if compiling for VisionOS.
|
||||
* A preprocessor macro that is only defined if compiling for visionOS.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*
|
||||
@@ -202,7 +202,7 @@
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
/**
|
||||
* A preprocessor macro that is only defined if compiling for iOS.
|
||||
* A preprocessor macro that is only defined if compiling for iOS or visionOS.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*
|
||||
|
||||
@@ -128,10 +128,10 @@ typedef struct SDL_FRect
|
||||
*/
|
||||
SDL_FORCE_INLINE void SDL_RectToFRect(const SDL_Rect *rect, SDL_FRect *frect)
|
||||
{
|
||||
frect->x = (float)rect->x;
|
||||
frect->y = (float)rect->y;
|
||||
frect->w = (float)rect->w;
|
||||
frect->h = (float)rect->h;
|
||||
frect->x = SDL_static_cast(float, rect->x);
|
||||
frect->y = SDL_static_cast(float, rect->y);
|
||||
frect->w = SDL_static_cast(float, rect->w);
|
||||
frect->h = SDL_static_cast(float, rect->h);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1704,8 +1704,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderCoordinatesToWindow(SDL_Renderer *ren
|
||||
*
|
||||
* \param renderer the rendering context.
|
||||
* \param event the event to modify.
|
||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||
* information.
|
||||
* \returns true if the event is converted or doesn't need conversion, or
|
||||
* false on failure; call SDL_GetError() for more information.
|
||||
*
|
||||
* \threadsafety This function should only be called on the main thread.
|
||||
*
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
* clue in debugging forensics and not something the app will parse in any
|
||||
* way.
|
||||
*
|
||||
* SDL_revision.h must be included in your program explicitly if you want
|
||||
* access to the SDL_REVISION constant.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_REVISION "Some arbitrary string decided at SDL build time"
|
||||
|
||||
@@ -1191,7 +1191,7 @@ typedef struct SDL_alignment_test
|
||||
void *b;
|
||||
} SDL_alignment_test;
|
||||
SDL_COMPILE_TIME_ASSERT(struct_alignment, sizeof(SDL_alignment_test) == (2 * sizeof(void *)));
|
||||
SDL_COMPILE_TIME_ASSERT(two_s_complement, (int)~(int)0 == (int)(-1));
|
||||
SDL_COMPILE_TIME_ASSERT(two_s_complement, SDL_static_cast(int, ~SDL_static_cast(int, 0)) == SDL_static_cast(int, -1));
|
||||
#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
|
||||
/** \endcond */
|
||||
|
||||
@@ -2667,7 +2667,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_memset4(void *dst, Uint32 val, size_t dwo
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*
|
||||
* \sa SDL_zero
|
||||
* \sa SDL_zeroa
|
||||
* \sa SDL_zerop
|
||||
*/
|
||||
#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x)))
|
||||
|
||||
@@ -5948,7 +5948,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode,
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)
|
||||
#define SDL_iconv_utf8_ucs2(S) SDL_reinterpret_cast(Uint16 *, SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1))
|
||||
|
||||
/**
|
||||
* Convert a UTF-8 string to UCS-4.
|
||||
@@ -5962,7 +5962,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode,
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)
|
||||
#define SDL_iconv_utf8_ucs4(S) SDL_reinterpret_cast(Uint32 *, SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1))
|
||||
|
||||
/**
|
||||
* Convert a wchar_t string to UTF-8.
|
||||
@@ -5976,7 +5976,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode,
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t))
|
||||
#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", SDL_reinterpret_cast(const char *, S), (SDL_wcslen(S)+1)*sizeof(wchar_t))
|
||||
|
||||
|
||||
/* force builds using Clang's static analysis tools to use literal C runtime
|
||||
|
||||
@@ -241,6 +241,12 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
|
||||
* left edge of the image, if this surface is being used as a cursor.
|
||||
* - `SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER`: the hotspot pixel offset from the
|
||||
* top edge of the image, if this surface is being used as a cursor.
|
||||
* - `SDL_PROP_SURFACE_ROTATION_NUMBER`: the number of degrees a surface's
|
||||
* data is meant to be rotated clockwise to make the image right-side up.
|
||||
* Default 0. This is used by the camera API, if a mobile device is oriented
|
||||
* differently than what its camera provides (i.e. - the camera always
|
||||
* provides portrait images but the phone is being held in landscape
|
||||
* orientation). Since SDL 3.4.0.
|
||||
*
|
||||
* \param surface the SDL_Surface structure to query.
|
||||
* \returns a valid property ID on success or 0 on failure; call
|
||||
@@ -257,6 +263,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac
|
||||
#define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap"
|
||||
#define SDL_PROP_SURFACE_HOTSPOT_X_NUMBER "SDL.surface.hotspot.x"
|
||||
#define SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER "SDL.surface.hotspot.y"
|
||||
#define SDL_PROP_SURFACE_ROTATION_NUMBER "SDL.surface.rotation"
|
||||
|
||||
/**
|
||||
* Set the colorspace used by a surface.
|
||||
@@ -502,6 +509,46 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface);
|
||||
*/
|
||||
extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
|
||||
|
||||
/**
|
||||
* Load a BMP or PNG image from a seekable SDL data stream.
|
||||
*
|
||||
* The new surface should be freed with SDL_DestroySurface(). Not doing so
|
||||
* will result in a memory leak.
|
||||
*
|
||||
* \param src the data stream for the surface.
|
||||
* \param closeio if true, calls SDL_CloseIO() on `src` before returning, even
|
||||
* in the case of an error.
|
||||
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \threadsafety It is safe to call this function from any thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.4.0.
|
||||
*
|
||||
* \sa SDL_DestroySurface
|
||||
* \sa SDL_LoadSurface
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio);
|
||||
|
||||
/**
|
||||
* Load a BMP or PNG image from a file.
|
||||
*
|
||||
* The new surface should be freed with SDL_DestroySurface(). Not doing so
|
||||
* will result in a memory leak.
|
||||
*
|
||||
* \param file the file to load.
|
||||
* \returns a pointer to a new SDL_Surface structure or NULL on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \threadsafety It is safe to call this function from any thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.4.0.
|
||||
*
|
||||
* \sa SDL_DestroySurface
|
||||
* \sa SDL_LoadSurface_IO
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface(const char *file);
|
||||
|
||||
/**
|
||||
* Load a BMP image from a seekable SDL data stream.
|
||||
*
|
||||
@@ -597,6 +644,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *f
|
||||
/**
|
||||
* Load a PNG image from a seekable SDL data stream.
|
||||
*
|
||||
* This is intended as a convenience function for loading images from trusted
|
||||
* sources. If you want to load arbitrary images you should use libpng or
|
||||
* another image loading library designed with security in mind.
|
||||
*
|
||||
* The new surface should be freed with SDL_DestroySurface(). Not doing so
|
||||
* will result in a memory leak.
|
||||
*
|
||||
@@ -619,6 +670,10 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadPNG_IO(SDL_IOStream *src, bool
|
||||
/**
|
||||
* Load a PNG image from a file.
|
||||
*
|
||||
* This is intended as a convenience function for loading images from trusted
|
||||
* sources. If you want to load arbitrary images you should use libpng or
|
||||
* another image loading library designed with security in mind.
|
||||
*
|
||||
* The new surface should be freed with SDL_DestroySurface(). Not doing so
|
||||
* will result in a memory leak.
|
||||
*
|
||||
|
||||
@@ -52,6 +52,7 @@ extern "C" {
|
||||
* \returns 0 if comparison succeeded, >0 (=number of pixels for which the comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ.
|
||||
*/
|
||||
int SDLCALL SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error);
|
||||
int SDLCALL SDLTest_CompareSurfacesIgnoreTransparentPixels(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error);
|
||||
|
||||
/**
|
||||
* Compares 2 memory blocks for equality
|
||||
|
||||
@@ -62,7 +62,7 @@ extern "C" {
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_MICRO_VERSION 2
|
||||
#define SDL_MICRO_VERSION 4
|
||||
|
||||
/**
|
||||
* This macro turns the version numbers into a numeric value.
|
||||
@@ -153,7 +153,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetVersion(void);
|
||||
*
|
||||
* This value is the revision of the code you are linking against and may be
|
||||
* different from the code you are compiling with, which is found in the
|
||||
* constant SDL_REVISION.
|
||||
* constant SDL_REVISION if you explicitly include SDL_revision.h
|
||||
*
|
||||
* The revision is an arbitrary string (a hash value) uniquely identifying the
|
||||
* exact revision of the SDL library in use, and is only useful in comparing
|
||||
|
||||
@@ -97,6 +97,8 @@ typedef Uint32 SDL_WindowID;
|
||||
* uninitialized will either return the user provided value, if one was set
|
||||
* prior to initialization, or NULL. See docs/README-wayland.md for more
|
||||
* information.
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER "SDL.video.wayland.wl_display"
|
||||
|
||||
@@ -488,7 +490,7 @@ typedef enum SDL_GLAttr
|
||||
SDL_GL_CONTEXT_FLAGS, /**< some combination of 0 or more of elements of the SDL_GLContextFlag enumeration; defaults to 0. */
|
||||
SDL_GL_CONTEXT_PROFILE_MASK, /**< type of GL context (Core, Compatibility, ES). See SDL_GLProfile; default value depends on platform. */
|
||||
SDL_GL_SHARE_WITH_CURRENT_CONTEXT, /**< OpenGL context sharing; defaults to 0. */
|
||||
SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB capable visual; defaults to 0. */
|
||||
SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB-capable visual if 1. Defaults to -1 ("don't care"). This is a request; GL drivers might not comply! */
|
||||
SDL_GL_CONTEXT_RELEASE_BEHAVIOR, /**< sets context the release behavior. See SDL_GLContextReleaseFlag; defaults to FLUSH. */
|
||||
SDL_GL_CONTEXT_RESET_NOTIFICATION, /**< set context reset notification. See SDL_GLContextResetNotification; defaults to NO_NOTIFICATION. */
|
||||
SDL_GL_CONTEXT_NO_ERROR,
|
||||
@@ -663,6 +665,11 @@ extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
|
||||
* - `SDL_PROP_DISPLAY_WAYLAND_WL_OUTPUT_POINTER`: the wl_output associated
|
||||
* with the display
|
||||
*
|
||||
* On Windows:
|
||||
*
|
||||
* - `SDL_PROP_DISPLAY_WINDOWS_HMONITOR_POINTER`: the monitor handle
|
||||
* (HMONITOR) associated with the display
|
||||
*
|
||||
* \param displayID the instance ID of the display to query.
|
||||
* \returns a valid property ID on success or 0 on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
@@ -676,6 +683,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_Displa
|
||||
#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled"
|
||||
#define SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER "SDL.display.KMSDRM.panel_orientation"
|
||||
#define SDL_PROP_DISPLAY_WAYLAND_WL_OUTPUT_POINTER "SDL.display.wayland.wl_output"
|
||||
#define SDL_PROP_DISPLAY_WINDOWS_HMONITOR_POINTER "SDL.display.windows.hmonitor"
|
||||
|
||||
/**
|
||||
* Get the name of a display in UTF-8 encoding.
|
||||
@@ -1323,6 +1331,12 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
|
||||
* - `SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER`: the `(__unsafe_unretained)`
|
||||
* NSView associated with the window, defaults to `[window contentView]`
|
||||
*
|
||||
* These are additional supported properties on iOS, tvOS, and visionOS:
|
||||
*
|
||||
* - `SDL_PROP_WINDOW_CREATE_WINDOWSCENE_POINTER`: the `(__unsafe_unretained)`
|
||||
* UIWindowScene associated with the window, defaults to the active window
|
||||
* scene.
|
||||
*
|
||||
* These are additional supported properties on Wayland:
|
||||
*
|
||||
* - `SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` - true if
|
||||
@@ -1431,6 +1445,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop
|
||||
#define SDL_PROP_WINDOW_CREATE_Y_NUMBER "SDL.window.create.y"
|
||||
#define SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER "SDL.window.create.cocoa.window"
|
||||
#define SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER "SDL.window.create.cocoa.view"
|
||||
#define SDL_PROP_WINDOW_CREATE_WINDOWSCENE_POINTER "SDL.window.create.uikit.windowscene"
|
||||
#define SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "SDL.window.create.wayland.surface_role_custom"
|
||||
#define SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN "SDL.window.create.wayland.create_egl_window"
|
||||
#define SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER "SDL.window.create.wayland.wl_surface"
|
||||
@@ -1866,6 +1881,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, in
|
||||
* \sa SDL_GetRenderOutputSize
|
||||
* \sa SDL_GetWindowSizeInPixels
|
||||
* \sa SDL_SetWindowSize
|
||||
* \sa SDL_EVENT_WINDOW_RESIZED
|
||||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h);
|
||||
|
||||
|
||||
@@ -218,6 +218,8 @@
|
||||
#cmakedefine HAVE_LIBURING_H 1
|
||||
#cmakedefine HAVE_FRIBIDI_H 1
|
||||
#cmakedefine SDL_FRIBIDI_DYNAMIC @SDL_FRIBIDI_DYNAMIC@
|
||||
#cmakedefine HAVE_LIBTHAI_H 1
|
||||
#cmakedefine SDL_LIBTHAI_DYNAMIC @SDL_LIBTHAI_DYNAMIC@
|
||||
|
||||
#cmakedefine HAVE_DDRAW_H 1
|
||||
#cmakedefine HAVE_DSOUND_H 1
|
||||
@@ -344,6 +346,7 @@
|
||||
#cmakedefine SDL_SENSOR_DUMMY 1
|
||||
#cmakedefine SDL_SENSOR_VITA 1
|
||||
#cmakedefine SDL_SENSOR_N3DS 1
|
||||
#cmakedefine SDL_SENSOR_EMSCRIPTEN 1
|
||||
|
||||
#cmakedefine SDL_SENSOR_PRIVATE 1
|
||||
|
||||
|
||||
38
src/SDL.c
38
src/SDL.c
@@ -189,6 +189,8 @@ static bool SDL_MainIsReady = false;
|
||||
static bool SDL_MainIsReady = true;
|
||||
#endif
|
||||
static SDL_ThreadID SDL_MainThreadID = 0;
|
||||
static SDL_ThreadID SDL_EventsThreadID = 0;
|
||||
static SDL_ThreadID SDL_VideoThreadID = 0;
|
||||
static bool SDL_bInMainQuit = false;
|
||||
static Uint8 SDL_SubsystemRefCount[32];
|
||||
|
||||
@@ -266,14 +268,16 @@ void SDL_SetMainReady(void)
|
||||
|
||||
bool SDL_IsMainThread(void)
|
||||
{
|
||||
if (SDL_MainThreadID == 0) {
|
||||
// Not initialized yet?
|
||||
return true;
|
||||
if (SDL_VideoThreadID) {
|
||||
return (SDL_GetCurrentThreadID() == SDL_VideoThreadID);
|
||||
}
|
||||
if (SDL_MainThreadID == SDL_GetCurrentThreadID()) {
|
||||
return true;
|
||||
if (SDL_EventsThreadID) {
|
||||
return (SDL_GetCurrentThreadID() == SDL_EventsThreadID);
|
||||
}
|
||||
return false;
|
||||
if (SDL_MainThreadID) {
|
||||
return (SDL_GetCurrentThreadID() == SDL_MainThreadID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize all the subsystems that require initialization before threads start
|
||||
@@ -281,6 +285,11 @@ void SDL_InitMainThread(void)
|
||||
{
|
||||
static bool done_info = false;
|
||||
|
||||
// If we haven't done it by now, mark this as the main thread
|
||||
if (SDL_MainThreadID == 0) {
|
||||
SDL_MainThreadID = SDL_GetCurrentThreadID();
|
||||
}
|
||||
|
||||
SDL_InitTLSData();
|
||||
SDL_InitEnvironment();
|
||||
SDL_InitTicks();
|
||||
@@ -335,6 +344,11 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
||||
if (flags & SDL_INIT_EVENTS) {
|
||||
if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) {
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS);
|
||||
|
||||
// Note which thread initialized events
|
||||
// This is the thread which should be pumping events
|
||||
SDL_EventsThreadID = SDL_GetCurrentThreadID();
|
||||
|
||||
if (!SDL_InitEvents()) {
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS);
|
||||
goto quit_and_error;
|
||||
@@ -354,12 +368,16 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
|
||||
goto quit_and_error;
|
||||
}
|
||||
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||
|
||||
// We initialize video on the main thread
|
||||
// On Apple platforms this is a requirement.
|
||||
// On other platforms, this is the definition.
|
||||
SDL_MainThreadID = SDL_GetCurrentThreadID();
|
||||
SDL_VideoThreadID = SDL_GetCurrentThreadID();
|
||||
#ifdef SDL_PLATFORM_APPLE
|
||||
SDL_assert(SDL_VideoThreadID == SDL_MainThreadID);
|
||||
#endif
|
||||
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||
if (!SDL_VideoInit(NULL)) {
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||
SDL_PushError();
|
||||
@@ -609,6 +627,7 @@ void SDL_QuitSubSystem(SDL_InitFlags flags)
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) {
|
||||
SDL_QuitRender();
|
||||
SDL_VideoQuit();
|
||||
SDL_VideoThreadID = 0;
|
||||
// video implies events
|
||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||
}
|
||||
@@ -619,6 +638,7 @@ void SDL_QuitSubSystem(SDL_InitFlags flags)
|
||||
if (flags & SDL_INIT_EVENTS) {
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) {
|
||||
SDL_QuitEvents();
|
||||
SDL_EventsThreadID = 0;
|
||||
}
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS);
|
||||
}
|
||||
@@ -760,6 +780,8 @@ const char *SDL_GetPlatform(void)
|
||||
return "Xbox One";
|
||||
#elif defined(SDL_PLATFORM_XBOXSERIES)
|
||||
return "Xbox Series X|S";
|
||||
#elif defined(SDL_PLATFORM_VISIONOS)
|
||||
return "visionOS";
|
||||
#elif defined(SDL_PLATFORM_IOS)
|
||||
return "iOS";
|
||||
#elif defined(SDL_PLATFORM_TVOS)
|
||||
|
||||
@@ -265,6 +265,7 @@ extern "C" {
|
||||
#include "SDL_utils_c.h"
|
||||
#include "SDL_hashtable.h"
|
||||
|
||||
|
||||
/* SDL_ExitProcess is not declared in any public header, although
|
||||
it is shared between some parts of SDL, because we don't want
|
||||
anything calling it without an extremely good reason. */
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
#include "core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
#if defined(SDL_PLATFORM_NGAGE)
|
||||
#include "core/ngage/SDL_ngage.h"
|
||||
#endif
|
||||
|
||||
// Simple log messages in SDL
|
||||
|
||||
#include "SDL_log_c.h"
|
||||
@@ -598,25 +602,6 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(SDL_PLATFORM_NGAGE)
|
||||
extern void NGAGE_vnprintf(char *buf, size_t size, const char *fmt, va_list ap);
|
||||
char buf[1024];
|
||||
NGAGE_vnprintf(buf, sizeof(buf), fmt, ap);
|
||||
|
||||
#ifdef ENABLE_FILE_LOG
|
||||
FILE* file;
|
||||
file = fopen("E:/SDL_Log.txt", "a");
|
||||
if (file)
|
||||
{
|
||||
vfprintf(file, fmt, ap);
|
||||
fprintf(file, "\n");
|
||||
(void)fclose(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Render into stack buffer
|
||||
va_copy(aq, ap);
|
||||
len = SDL_vsnprintf(stack_buf, sizeof(stack_buf), fmt, aq);
|
||||
@@ -627,15 +612,21 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S
|
||||
}
|
||||
|
||||
// If message truncated, allocate and re-render
|
||||
if (len >= sizeof(stack_buf) && SDL_size_add_check_overflow(len, 1, &len_plus_term)) {
|
||||
// Allocate exactly what we need, including the zero-terminator
|
||||
message = (char *)SDL_malloc(len_plus_term);
|
||||
if (!message) {
|
||||
return;
|
||||
if (len >= sizeof(stack_buf)) {
|
||||
if (SDL_size_add_check_overflow(len, 1, &len_plus_term)) {
|
||||
// Allocate exactly what we need, including the zero-terminator
|
||||
message = (char *)SDL_malloc(len_plus_term);
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
va_copy(aq, ap);
|
||||
len = SDL_vsnprintf(message, len_plus_term, fmt, aq);
|
||||
va_end(aq);
|
||||
} else {
|
||||
// Allocation would overflow, use truncated message
|
||||
message = stack_buf;
|
||||
len = sizeof(stack_buf);
|
||||
}
|
||||
va_copy(aq, ap);
|
||||
len = SDL_vsnprintf(message, len_plus_term, fmt, aq);
|
||||
va_end(aq);
|
||||
} else {
|
||||
message = stack_buf;
|
||||
}
|
||||
@@ -799,7 +790,15 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
|
||||
}
|
||||
#elif defined(SDL_PLATFORM_NGAGE)
|
||||
{
|
||||
/* Nothing to do here. */
|
||||
NGAGE_DebugPrintf("%s%s", GetLogPriorityPrefix(priority), message);
|
||||
#ifdef ENABLE_FILE_LOG
|
||||
FILE *pFile;
|
||||
pFile = fopen("E:/SDL_Log.txt", "a");
|
||||
if (pFile) {
|
||||
(void)fprintf(pFile, "%s%s\n", GetLogPriorityPrefix(priority), message);
|
||||
(void)fclose(pFile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_STDIO_H) && \
|
||||
|
||||
@@ -250,7 +250,7 @@ static bool SDLCALL LogOneLeakedObject(void *userdata, const SDL_HashTable *tabl
|
||||
#undef SDLOBJTYPECASE
|
||||
default: break;
|
||||
}
|
||||
SDL_Log("Leaked %s (%p)", type, object);
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Leaked %s (%p)", type, object);
|
||||
return true; // keep iterating.
|
||||
}
|
||||
|
||||
@@ -259,7 +259,6 @@ void SDL_SetObjectsInvalid(void)
|
||||
if (SDL_ShouldQuit(&SDL_objects_init)) {
|
||||
// Log any leaked objects
|
||||
SDL_IterateHashTable(SDL_objects, LogOneLeakedObject, NULL);
|
||||
SDL_assert(SDL_HashTableEmpty(SDL_objects));
|
||||
SDL_DestroyHashTable(SDL_objects);
|
||||
SDL_objects = NULL;
|
||||
SDL_SetInitialized(&SDL_objects_init, false);
|
||||
|
||||
@@ -91,7 +91,7 @@ bool SDL_TryLockSpinlock(SDL_SpinLock *lock)
|
||||
: "cc", "memory");
|
||||
return result == 0;
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
#elif (defined(__GNUC__) || defined(__TINYC__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
int result;
|
||||
__asm__ __volatile__(
|
||||
"lock ; xchgl %0, (%1)\n"
|
||||
|
||||
@@ -1298,7 +1298,11 @@ void SDL_PlaybackAudioThreadShutdown(SDL_AudioDevice *device)
|
||||
const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
// Wait for the audio to drain if device didn't die.
|
||||
if (!SDL_GetAtomicInt(&device->zombie)) {
|
||||
SDL_Delay(((frames * 1000) / device->spec.freq) * 2);
|
||||
int delay = ((frames * 1000) / device->spec.freq) * 2;
|
||||
if (delay > 100) {
|
||||
delay = 100;
|
||||
}
|
||||
SDL_Delay(delay);
|
||||
}
|
||||
current_audio.impl.ThreadDeinit(device);
|
||||
SDL_AudioThreadFinalize(device);
|
||||
|
||||
@@ -484,8 +484,6 @@ static void ALSA_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
if (device->hidden->pcm) {
|
||||
// Wait for the submitted audio to drain. ALSA_snd_pcm_drop() can hang, so don't use that.
|
||||
SDL_Delay(((device->sample_frames * 1000) / device->spec.freq) * 2);
|
||||
ALSA_snd_pcm_close(device->hidden->pcm);
|
||||
}
|
||||
SDL_free(device->hidden->mixbuf);
|
||||
|
||||
@@ -206,7 +206,7 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
|
||||
{
|
||||
#ifdef HAVE_MMDEVICEAPI_H
|
||||
if (SupportsIMMDevice) {
|
||||
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording, SDL_AUDIO_UNKNOWN);
|
||||
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording, SDL_AUDIO_UNKNOWN, false);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
||||
@@ -602,6 +602,71 @@ static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata)
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
|
||||
}
|
||||
|
||||
// Channel maps that match the order in SDL_Audio.h
|
||||
static const pa_channel_position_t Pulse_map_1[] = { PA_CHANNEL_POSITION_MONO };
|
||||
static const pa_channel_position_t Pulse_map_2[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT };
|
||||
|
||||
static const pa_channel_position_t Pulse_map_3[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_LFE };
|
||||
|
||||
static const pa_channel_position_t Pulse_map_4[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT };
|
||||
|
||||
static const pa_channel_position_t Pulse_map_5[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_LFE,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT };
|
||||
|
||||
static const pa_channel_position_t Pulse_map_6[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT };
|
||||
|
||||
static const pa_channel_position_t Pulse_map_7[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
|
||||
PA_CHANNEL_POSITION_REAR_CENTER,
|
||||
PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT };
|
||||
|
||||
static const pa_channel_position_t Pulse_map_8[] = { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
||||
PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT };
|
||||
|
||||
#define COPY_CHANNEL_MAP(c) SDL_memcpy(pacmap->map, Pulse_map_##c, sizeof(Pulse_map_##c))
|
||||
|
||||
static void PulseCreateChannelMap(pa_channel_map *pacmap, uint8_t channels)
|
||||
{
|
||||
SDL_assert(channels <= PA_CHANNELS_MAX);
|
||||
|
||||
pacmap->channels = channels;
|
||||
|
||||
switch (channels) {
|
||||
case 1:
|
||||
COPY_CHANNEL_MAP(1);
|
||||
break;
|
||||
case 2:
|
||||
COPY_CHANNEL_MAP(2);
|
||||
break;
|
||||
case 3:
|
||||
COPY_CHANNEL_MAP(3);
|
||||
break;
|
||||
case 4:
|
||||
COPY_CHANNEL_MAP(4);
|
||||
break;
|
||||
case 5:
|
||||
COPY_CHANNEL_MAP(5);
|
||||
break;
|
||||
case 6:
|
||||
COPY_CHANNEL_MAP(6);
|
||||
break;
|
||||
case 7:
|
||||
COPY_CHANNEL_MAP(7);
|
||||
break;
|
||||
case 8:
|
||||
COPY_CHANNEL_MAP(8);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
const bool recording = device->recording;
|
||||
@@ -690,9 +755,8 @@ static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
|
||||
// The SDL ALSA output hints us that we use Windows' channel mapping
|
||||
// https://bugzilla.libsdl.org/show_bug.cgi?id=110
|
||||
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX);
|
||||
|
||||
PulseCreateChannelMap(&pacmap, device->spec.channels);
|
||||
|
||||
h->stream = PULSEAUDIO_pa_stream_new(
|
||||
pulseaudio_context,
|
||||
|
||||
@@ -62,6 +62,7 @@ static const IID SDL_IID_IAudioClient3 = { 0x7ed4ee07, 0x8e67, 0x4cd4, { 0x8c, 0
|
||||
#endif //
|
||||
|
||||
static bool immdevice_initialized = false;
|
||||
static bool supports_recording_on_playback_devices = false;
|
||||
|
||||
// WASAPI is _really_ particular about various things happening on the same thread, for COM and such,
|
||||
// so we proxy various stuff to a single background thread to manage.
|
||||
@@ -329,7 +330,7 @@ typedef struct
|
||||
static bool mgmtthrtask_DetectDevices(void *userdata)
|
||||
{
|
||||
mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata;
|
||||
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording, SDL_AUDIO_F32);
|
||||
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording, SDL_AUDIO_F32, supports_recording_on_playback_devices);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -346,7 +347,7 @@ static void WASAPI_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
|
||||
void WASAPI_DisconnectDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// don't block in here; IMMDevice's own thread needs to return or everything will deadlock.
|
||||
if (device && device->hidden && SDL_CompareAndSwapAtomicInt(&device->hidden->device_disconnecting, 0, 1)) {
|
||||
if (device && (!device->hidden || SDL_CompareAndSwapAtomicInt(&device->hidden->device_disconnecting, 0, 1))) {
|
||||
SDL_AudioDeviceDisconnected(device); // this proxies the work to the main thread now, so no point in proxying to the management thread.
|
||||
}
|
||||
}
|
||||
@@ -446,6 +447,8 @@ static bool mgmtthrtask_ActivateDevice(void *userdata)
|
||||
return false; // This is already set by SDL_IMMDevice_Get
|
||||
}
|
||||
|
||||
device->hidden->isplayback = !SDL_IMMDevice_GetIsCapture(immdevice);
|
||||
|
||||
// this is _not_ async in standard win32, yay!
|
||||
HRESULT ret = IMMDevice_Activate(immdevice, &SDL_IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&device->hidden->client);
|
||||
IMMDevice_Release(immdevice);
|
||||
@@ -725,6 +728,10 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
|
||||
|
||||
newspec.freq = waveformat->nSamplesPerSec;
|
||||
|
||||
if (device->recording && device->hidden->isplayback) {
|
||||
streamflags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
|
||||
}
|
||||
|
||||
streamflags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||
|
||||
int new_sample_frames = 0;
|
||||
@@ -739,6 +746,9 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
|
||||
SDL_zero(audioProps);
|
||||
audioProps.cbSize = sizeof(audioProps);
|
||||
|
||||
// Setting AudioCategory_GameChat breaks audio on several devices, including Behringer U-PHORIA UM2 and RODE NT-USB Mini.
|
||||
// We'll disable this for now until we understand more about what's happening.
|
||||
#if 0
|
||||
const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_ROLE);
|
||||
if (hint && *hint) {
|
||||
if (SDL_strcasecmp(hint, "Communications") == 0) {
|
||||
@@ -754,6 +764,7 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
|
||||
audioProps.eCategory = AudioCategory_Media;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SDL_GetHintBoolean(SDL_HINT_AUDIO_DEVICE_RAW_STREAM, false)) {
|
||||
audioProps.Options = AUDCLNT_STREAMOPTIONS_RAW;
|
||||
@@ -974,6 +985,7 @@ static bool WASAPI_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle;
|
||||
|
||||
impl->HasRecordingSupport = true;
|
||||
supports_recording_on_playback_devices = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ struct SDL_PrivateAudioData
|
||||
SDL_AtomicInt device_disconnecting;
|
||||
bool device_lost;
|
||||
bool device_dead;
|
||||
bool isplayback;
|
||||
};
|
||||
|
||||
// win32 implementation calls into these.
|
||||
|
||||
@@ -150,7 +150,7 @@ static size_t GetFrameBufLen(const SDL_CameraSpec *spec)
|
||||
return wxh * SDL_BYTESPERPIXEL(fmt);
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult ZombieAcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult ZombieAcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
const SDL_CameraSpec *spec = &device->actual_spec;
|
||||
|
||||
@@ -832,9 +832,10 @@ bool SDL_CameraThreadIterate(SDL_Camera *device)
|
||||
SDL_Surface *output_surface = NULL;
|
||||
SurfaceList *slist = NULL;
|
||||
Uint64 timestampNS = 0;
|
||||
int rotation = 0;
|
||||
|
||||
// AcquireFrame SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitDevice instead!
|
||||
const SDL_CameraFrameResult rc = device->AcquireFrame(device, device->acquire_surface, ×tampNS);
|
||||
const SDL_CameraFrameResult rc = device->AcquireFrame(device, device->acquire_surface, ×tampNS, &rotation);
|
||||
|
||||
if (rc == SDL_CAMERA_FRAME_READY) { // new frame acquired!
|
||||
#if DEBUG_CAMERA
|
||||
@@ -928,6 +929,8 @@ bool SDL_CameraThreadIterate(SDL_Camera *device)
|
||||
acquired->pixels = NULL;
|
||||
acquired->pitch = 0;
|
||||
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(output_surface), SDL_PROP_SURFACE_ROTATION_NUMBER, rotation);
|
||||
|
||||
// make the filled output surface available to the app.
|
||||
SDL_LockMutex(device->lock);
|
||||
slist->next = device->filled_output_surfaces.next;
|
||||
@@ -1093,7 +1096,6 @@ static void ChooseBestCameraSpec(SDL_Camera *device, const SDL_CameraSpec *spec,
|
||||
// that.
|
||||
|
||||
SDL_zerop(closest);
|
||||
SDL_assert(((Uint32) SDL_PIXELFORMAT_UNKNOWN) == 0); // since we SDL_zerop'd to this value.
|
||||
|
||||
if (device->num_specs == 0) { // device listed no specs! You get whatever you want!
|
||||
if (spec) {
|
||||
|
||||
@@ -99,7 +99,7 @@ struct SDL_Camera
|
||||
|
||||
// These are, initially, set from camera_driver, but we might swap them out with Zombie versions on disconnect/failure.
|
||||
bool (*WaitDevice)(SDL_Camera *device);
|
||||
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS);
|
||||
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation);
|
||||
void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame);
|
||||
|
||||
// All supported formats/dimensions for this device.
|
||||
@@ -167,13 +167,18 @@ struct SDL_Camera
|
||||
struct SDL_PrivateCameraData *hidden;
|
||||
};
|
||||
|
||||
|
||||
// Note that for AcquireFrame, `rotation` is degrees, with positive values rotating clockwise. This is the amount to rotate an image so it would be right-side up.
|
||||
// Rotations should be in 90 degree increments at this time (landscape to portrait, or upside down to right side up, etc).
|
||||
// Most platforms won't care about this, but mobile devices might need to deal with the device itself being physically rotated, causing the fixed-orientation camera to be presenting sideways images.
|
||||
|
||||
typedef struct SDL_CameraDriverImpl
|
||||
{
|
||||
void (*DetectDevices)(void);
|
||||
bool (*OpenDevice)(SDL_Camera *device, const SDL_CameraSpec *spec);
|
||||
void (*CloseDevice)(SDL_Camera *device);
|
||||
bool (*WaitDevice)(SDL_Camera *device);
|
||||
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS); // set frame->pixels, frame->pitch, and *timestampNS!
|
||||
SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation); // set frame->pixels, frame->pitch, *timestampNS, and *rotation!
|
||||
void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame); // Reclaim frame->pixels and frame->pitch!
|
||||
void (*FreeDeviceHandle)(SDL_Camera *device); // SDL is done with this device; free the handle from SDL_AddCamera()
|
||||
void (*Deinitialize)(void);
|
||||
|
||||
@@ -149,6 +149,7 @@ struct SDL_PrivateCameraData
|
||||
ACaptureRequest *request;
|
||||
ACameraCaptureSession *session;
|
||||
SDL_CameraSpec requested_spec;
|
||||
int rotation; // degrees to rotate clockwise to get from camera's static orientation to device's native orientation. Apply this plus current phone rotation to get upright image!
|
||||
};
|
||||
|
||||
static bool SetErrorStr(const char *what, const char *errstr, const int rc)
|
||||
@@ -295,7 +296,7 @@ static bool ANDROIDCAMERA_WaitDevice(SDL_Camera *device)
|
||||
return true; // this isn't used atm, since we run our own thread via onImageAvailable callbacks.
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY;
|
||||
media_status_t res;
|
||||
@@ -366,6 +367,21 @@ static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_
|
||||
|
||||
pAImage_delete(image);
|
||||
|
||||
int dev_rotation = 0;
|
||||
switch (Android_JNI_GetDisplayCurrentOrientation()) {
|
||||
case SDL_ORIENTATION_PORTRAIT: dev_rotation = 0; break;
|
||||
case SDL_ORIENTATION_LANDSCAPE: dev_rotation = 90; break;
|
||||
case SDL_ORIENTATION_PORTRAIT_FLIPPED: dev_rotation = 180; break;
|
||||
case SDL_ORIENTATION_LANDSCAPE_FLIPPED: dev_rotation = 270; break;
|
||||
default: SDL_assert(!"Unexpected device rotation!"); dev_rotation = 0; break;
|
||||
}
|
||||
|
||||
if (device->position == SDL_CAMERA_POSITION_BACK_FACING) {
|
||||
dev_rotation = -dev_rotation; // we want to subtract this value, instead of add, if back-facing.
|
||||
}
|
||||
|
||||
*rotation = dev_rotation + device->hidden->rotation; // current phone orientation, static camera orientation in relation to phone.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -494,10 +510,23 @@ static bool PrepareCamera(SDL_Camera *device)
|
||||
imglistener.context = device;
|
||||
imglistener.onImageAvailable = onImageAvailable;
|
||||
|
||||
|
||||
const char *devid = (const char *) device->handle;
|
||||
|
||||
device->hidden->rotation = 0;
|
||||
ACameraMetadata *metadata = NULL;
|
||||
ACameraMetadata_const_entry orientationentry;
|
||||
if (pACameraManager_getCameraCharacteristics(cameraMgr, devid, &metadata) == ACAMERA_OK) {
|
||||
if (pACameraMetadata_getConstEntry(metadata, ACAMERA_SENSOR_ORIENTATION, &orientationentry) == ACAMERA_OK) {
|
||||
device->hidden->rotation = (int) (*orientationentry.data.i32 % 360);
|
||||
}
|
||||
pACameraMetadata_free(metadata);
|
||||
}
|
||||
|
||||
// just in case SDL_OpenCamera is overwriting device->spec as CameraPermissionCallback runs, we work from a different copy.
|
||||
const SDL_CameraSpec *spec = &device->hidden->requested_spec;
|
||||
|
||||
if ((res = pACameraManager_openCamera(cameraMgr, (const char *) device->handle, &dev_callbacks, &device->hidden->device)) != ACAMERA_OK) {
|
||||
if ((res = pACameraManager_openCamera(cameraMgr, devid, &dev_callbacks, &device->hidden->device)) != ACAMERA_OK) {
|
||||
return SetCameraError("Failed to open camera", res);
|
||||
} else if ((res2 = pAImageReader_new(spec->width, spec->height, format_sdl_to_android(spec->format), 10 /* nb buffers */, &device->hidden->reader)) != AMEDIA_OK) {
|
||||
return SetMediaError("Error AImageReader_new", res2);
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <CoreMedia/CoreMedia.h>
|
||||
|
||||
#if defined(SDL_PLATFORM_IOS) && !defined(SDL_PLATFORM_TVOS)
|
||||
#define USE_UIKIT_DEVICE_ROTATION
|
||||
#endif
|
||||
|
||||
#ifdef USE_UIKIT_DEVICE_ROTATION
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Need to link with:: CoreMedia CoreVideo
|
||||
*
|
||||
@@ -77,6 +85,9 @@ static void CoreMediaFormatToSDL(FourCharCode fmt, SDL_PixelFormat *pixel_format
|
||||
@property(nonatomic, retain) AVCaptureSession *session;
|
||||
@property(nonatomic, retain) SDLCaptureVideoDataOutputSampleBufferDelegate *delegate;
|
||||
@property(nonatomic, assign) CMSampleBufferRef current_sample;
|
||||
#ifdef USE_UIKIT_DEVICE_ROTATION
|
||||
@property(nonatomic, assign) UIDeviceOrientation last_device_orientation;
|
||||
#endif
|
||||
@end
|
||||
|
||||
@implementation SDLPrivateCameraData
|
||||
@@ -146,7 +157,7 @@ static bool COREMEDIA_WaitDevice(SDL_Camera *device)
|
||||
return true; // this isn't used atm, since we run our own thread out of Grand Central Dispatch.
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY;
|
||||
SDLPrivateCameraData *hidden = (__bridge SDLPrivateCameraData *) device->hidden;
|
||||
@@ -219,6 +230,37 @@ static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surf
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(image, 0);
|
||||
|
||||
#ifdef USE_UIKIT_DEVICE_ROTATION
|
||||
UIDeviceOrientation device_orientation = [[UIDevice currentDevice] orientation];
|
||||
if (!UIDeviceOrientationIsValidInterfaceOrientation(device_orientation)) {
|
||||
device_orientation = hidden.last_device_orientation; // possible the phone is laying flat or something went wrong, just stay with the last known-good orientation.
|
||||
} else {
|
||||
hidden.last_device_orientation = device_orientation; // update the last known-good orientation for later.
|
||||
}
|
||||
|
||||
const UIInterfaceOrientation ui_orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
// there is probably math for this, but this is easy to slap into a table.
|
||||
// rotation = rotations[uiorientation-1][devorientation-1];
|
||||
if (device->position == SDL_CAMERA_POSITION_BACK_FACING) {
|
||||
static const int back_rotations[4][4] = {
|
||||
{ 90, 90, 90, 90 }, // ui portrait
|
||||
{ 270, 270, 270, 270 }, // ui portait upside down
|
||||
{ 0, 0, 0, 0 }, // ui landscape left
|
||||
{ 180, 180, 180, 180 } // ui landscape right
|
||||
};
|
||||
*rotation = back_rotations[ui_orientation - 1][device_orientation - 1];
|
||||
} else {
|
||||
static const int front_rotations[4][4] = {
|
||||
{ 90, 90, 270, 270 }, // ui portrait
|
||||
{ 270, 270, 90, 90 }, // ui portait upside down
|
||||
{ 0, 0, 180, 180 }, // ui landscape left
|
||||
{ 180, 180, 0, 0 } // ui landscape right
|
||||
};
|
||||
*rotation = front_rotations[ui_orientation - 1][device_orientation - 1];
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -231,6 +273,10 @@ static void COREMEDIA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame)
|
||||
static void COREMEDIA_CloseDevice(SDL_Camera *device)
|
||||
{
|
||||
if (device && device->hidden) {
|
||||
#ifdef USE_UIKIT_DEVICE_ROTATION
|
||||
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
|
||||
#endif
|
||||
|
||||
SDLPrivateCameraData *hidden = (SDLPrivateCameraData *) CFBridgingRelease(device->hidden);
|
||||
device->hidden = NULL;
|
||||
|
||||
@@ -358,6 +404,28 @@ static bool COREMEDIA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
|
||||
hidden.session = session;
|
||||
hidden.delegate = delegate;
|
||||
hidden.current_sample = NULL;
|
||||
|
||||
#ifdef USE_UIKIT_DEVICE_ROTATION
|
||||
// When using a camera, we turn on device orientation tracking. The docs note that this turns on
|
||||
// the device's accelerometer, so I assume this burns power, so we don't leave this running all
|
||||
// the time. These calls nest, so we just need to call the matching `end` message when we close.
|
||||
// You _can_ get an actual events through this mechanism, but we just want to be able to call
|
||||
// -[UIDevice orientation], which will update with real info while notificatons are enabled.
|
||||
UIDevice *uidevice = [UIDevice currentDevice];
|
||||
[uidevice beginGeneratingDeviceOrientationNotifications];
|
||||
hidden.last_device_orientation = uidevice.orientation;
|
||||
if (!UIDeviceOrientationIsValidInterfaceOrientation(hidden.last_device_orientation)) {
|
||||
// accelerometer isn't ready yet or the phone is laying flat or something. Just try to guess from how the UI is oriented at the moment.
|
||||
switch ([UIApplication sharedApplication].statusBarOrientation) {
|
||||
case UIInterfaceOrientationPortrait: hidden.last_device_orientation = UIDeviceOrientationPortrait; break;
|
||||
case UIInterfaceOrientationPortraitUpsideDown: hidden.last_device_orientation = UIDeviceOrientationPortraitUpsideDown; break;
|
||||
case UIInterfaceOrientationLandscapeLeft: hidden.last_device_orientation = UIDeviceOrientationLandscapeRight; break; // Apple docs say UI and device orientations are reversed in landscape.
|
||||
case UIInterfaceOrientationLandscapeRight: hidden.last_device_orientation = UIDeviceOrientationLandscapeLeft; break;
|
||||
default: hidden.last_device_orientation = UIDeviceOrientationPortrait; break; // oh well.
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
device->hidden = (struct SDL_PrivateCameraData *)CFBridgingRetain(hidden);
|
||||
|
||||
[session startRunning]; // !!! FIXME: docs say this can block while camera warms up and shouldn't be done on main thread. Maybe push through `queue`?
|
||||
|
||||
@@ -38,7 +38,7 @@ static bool DUMMYCAMERA_WaitDevice(SDL_Camera *device)
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult DUMMYCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult DUMMYCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return SDL_CAMERA_FRAME_ERROR;
|
||||
|
||||
@@ -39,7 +39,7 @@ static bool EMSCRIPTENCAMERA_WaitDevice(SDL_Camera *device)
|
||||
return false;
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
void *rgba = SDL_malloc(device->actual_spec.width * device->actual_spec.height * 4);
|
||||
if (!rgba) {
|
||||
|
||||
@@ -430,7 +430,7 @@ static void SDLCALL CleanupIMFMediaBuffer(void *userdata, void *value)
|
||||
SDL_free(objs);
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
SDL_assert(device->hidden->current_sample != NULL);
|
||||
|
||||
@@ -562,7 +562,7 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_CopyFrame(SDL_Surface *frame, const
|
||||
return SDL_CAMERA_FRAME_READY;
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
SDL_assert(device->hidden->current_sample != NULL);
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ static struct param *param_add(struct spa_list *params,
|
||||
id = SPA_POD_OBJECT_ID(param);
|
||||
}
|
||||
|
||||
p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0));
|
||||
p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0)); // This should NOT be SDL_malloc()
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -577,7 +577,7 @@ static bool PIPEWIRECAMERA_WaitDevice(SDL_Camera *device)
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult PIPEWIRECAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult PIPEWIRECAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
struct pw_buffer *b;
|
||||
|
||||
@@ -950,7 +950,7 @@ static void hotplug_registry_global_callback(void *object, uint32_t id,
|
||||
g->permissions = permissions;
|
||||
g->props = props ? PIPEWIRE_pw_properties_new_dict(props) : NULL;
|
||||
g->proxy = proxy;
|
||||
g->name = strdup(name);
|
||||
g->name = strdup(name); // This should NOT be SDL_strdup()
|
||||
spa_list_init(&g->pending_list);
|
||||
spa_list_init(&g->param_list);
|
||||
spa_list_append(&hotplug.global_list, &g->link);
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
#include <unistd.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#ifndef V4L2_PIX_FMT_RGBX32
|
||||
#define V4L2_PIX_FMT_RGBX32 v4l2_fourcc('X','B','2','4')
|
||||
#endif
|
||||
#ifndef V4L2_CAP_DEVICE_CAPS
|
||||
// device_caps was added to struct v4l2_capability as of kernel 3.4.
|
||||
#define device_caps reserved[0]
|
||||
@@ -122,7 +125,7 @@ static bool V4L2_WaitDevice(SDL_Camera *device)
|
||||
return false;
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
const int fd = device->hidden->fd;
|
||||
const io_method io = device->hidden->io;
|
||||
@@ -418,6 +421,7 @@ static void format_v4l2_to_sdl(Uint32 fmt, SDL_PixelFormat *format, SDL_Colorspa
|
||||
#define CASE(x, y, z) case x: *format = y; *colorspace = z; return
|
||||
CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED);
|
||||
CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_MJPG, SDL_COLORSPACE_SRGB);
|
||||
CASE(V4L2_PIX_FMT_RGBX32, SDL_PIXELFORMAT_RGBX32, SDL_COLORSPACE_SRGB);
|
||||
#undef CASE
|
||||
default:
|
||||
#if DEBUG_CAMERA
|
||||
@@ -439,6 +443,7 @@ static Uint32 format_sdl_to_v4l2(SDL_PixelFormat fmt)
|
||||
#define CASE(y, x) case x: return y
|
||||
CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2);
|
||||
CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_MJPG);
|
||||
CASE(V4L2_PIX_FMT_RGBX32, SDL_PIXELFORMAT_RGBX32);
|
||||
#undef CASE
|
||||
default:
|
||||
return 0;
|
||||
@@ -570,7 +575,7 @@ static bool V4L2_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
|
||||
setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (xioctl(fd, VIDIOC_G_PARM, &setfps) == 0) {
|
||||
if ( (setfps.parm.capture.timeperframe.denominator != spec->framerate_numerator) ||
|
||||
(setfps.parm.capture.timeperframe.numerator = spec->framerate_denominator) ) {
|
||||
(setfps.parm.capture.timeperframe.numerator != spec->framerate_denominator) ) {
|
||||
setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
setfps.parm.capture.timeperframe.numerator = spec->framerate_denominator;
|
||||
setfps.parm.capture.timeperframe.denominator = spec->framerate_numerator;
|
||||
|
||||
@@ -139,7 +139,7 @@ static bool VITACAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec
|
||||
info->format = SCE_CAMERA_FORMAT_YUV420_PLANE;
|
||||
info->pitch = 0; // same size surface
|
||||
|
||||
info->sizeIBase = spec->width * spec->height;;
|
||||
info->sizeIBase = spec->width * spec->height;
|
||||
info->sizeUBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
|
||||
info->sizeVBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
|
||||
|
||||
@@ -190,7 +190,7 @@ static bool VITACAMERA_WaitDevice(SDL_Camera *device)
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS, int *rotation)
|
||||
{
|
||||
SceCameraRead read = {0};
|
||||
read.size = sizeof(SceCameraRead);
|
||||
|
||||
@@ -184,7 +184,6 @@ Sint32 JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
(void)vm;
|
||||
(void)reserved;
|
||||
SDL_Unsupported();
|
||||
return -1; // JNI_ERR
|
||||
return 0x00010004; // JNI_VERSION_1_4
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -768,9 +768,6 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
||||
checkJNIReady();
|
||||
}
|
||||
|
||||
// SDL main function prototype
|
||||
typedef int (*SDL_main_func)(int argc, char *argv[]);
|
||||
|
||||
static int run_count = 0;
|
||||
static bool allow_recreate_activity;
|
||||
static bool allow_recreate_activity_set;
|
||||
@@ -840,47 +837,61 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls,
|
||||
function_name = (*env)->GetStringUTFChars(env, function, NULL);
|
||||
SDL_main = (SDL_main_func)dlsym(library_handle, function_name);
|
||||
if (SDL_main) {
|
||||
int i;
|
||||
int argc;
|
||||
int len;
|
||||
char **argv;
|
||||
bool isstack;
|
||||
// Use the name "app_process" for argv[0] so PHYSFS_platformCalcBaseDir() works.
|
||||
// https://github.com/love2d/love-android/issues/24
|
||||
// (note that PhysicsFS hasn't used argv on Android in a long time, but we'll keep this for compat at least for SDL3's lifetime. --ryan.)
|
||||
const char *argv0 = "app_process";
|
||||
const int len = (*env)->GetArrayLength(env, array); // argv elements, not counting argv[0].
|
||||
|
||||
// Prepare the arguments.
|
||||
len = (*env)->GetArrayLength(env, array);
|
||||
argv = SDL_small_alloc(char *, 1 + len + 1, &isstack); // !!! FIXME: check for NULL
|
||||
argc = 0;
|
||||
/* Use the name "app_process" so PHYSFS_platformCalcBaseDir() works.
|
||||
https://github.com/love2d/love-android/issues/24
|
||||
*/
|
||||
argv[argc++] = SDL_strdup("app_process");
|
||||
for (i = 0; i < len; ++i) {
|
||||
char *arg = NULL;
|
||||
size_t total_alloc_len = (SDL_strlen(argv0) + 1) + ((len + 2) * sizeof (char *)); // len+2 to allocate an array that also holds argv0 and a NULL terminator.
|
||||
for (int i = 0; i < len; ++i) {
|
||||
total_alloc_len++; // null terminator.
|
||||
jstring string = (*env)->GetObjectArrayElement(env, array, i);
|
||||
if (string) {
|
||||
const char *utf = (*env)->GetStringUTFChars(env, string, 0);
|
||||
if (utf) {
|
||||
arg = SDL_strdup(utf);
|
||||
total_alloc_len += SDL_strlen(utf) + 1;
|
||||
(*env)->ReleaseStringUTFChars(env, string, utf);
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, string);
|
||||
}
|
||||
if (arg == NULL) {
|
||||
arg = SDL_strdup("");
|
||||
}
|
||||
|
||||
void *args = malloc(total_alloc_len); // This should NOT be SDL_malloc()
|
||||
if (!args) { // uhoh.
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "nativeRunMain(): Out of memory parsing command line!");
|
||||
} else {
|
||||
size_t remain = total_alloc_len - (sizeof (char *) * (len + 2));
|
||||
int argc = 0;
|
||||
char **argv = (char **) args;
|
||||
char *ptr = (char *) &argv[len + 2];
|
||||
size_t cpy = SDL_strlcpy(ptr, argv0, remain) + 1;
|
||||
argv[argc++] = ptr;
|
||||
SDL_assert(cpy <= remain); remain -= cpy; ptr += cpy;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
jstring string = (*env)->GetObjectArrayElement(env, array, i);
|
||||
const char *utf = string ? (*env)->GetStringUTFChars(env, string, 0) : NULL;
|
||||
cpy = SDL_strlcpy(ptr, utf ? utf : "", remain) + 1;
|
||||
if (cpy < remain) {
|
||||
argv[argc++] = ptr;
|
||||
remain -= cpy;
|
||||
ptr += cpy;
|
||||
}
|
||||
if (utf) {
|
||||
(*env)->ReleaseStringUTFChars(env, string, utf);
|
||||
}
|
||||
if (string) {
|
||||
(*env)->DeleteLocalRef(env, string);
|
||||
}
|
||||
}
|
||||
argv[argc++] = arg;
|
||||
argv[argc] = NULL;
|
||||
|
||||
// Run the application.
|
||||
status = SDL_RunApp(argc, argv, SDL_main, NULL);
|
||||
|
||||
// Release the arguments.
|
||||
free(args); // This should NOT be SDL_free()
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
|
||||
// Run the application.
|
||||
status = SDL_main(argc, argv);
|
||||
|
||||
// Release the arguments.
|
||||
for (i = 0; i < argc; ++i) {
|
||||
SDL_free(argv[i]);
|
||||
}
|
||||
SDL_small_free(argv, isstack);
|
||||
|
||||
} else {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "nativeRunMain(): Couldn't find function %s in library %s", function_name, library_file);
|
||||
}
|
||||
@@ -1873,6 +1884,17 @@ static void Internal_Android_Destroy_AssetManager(void)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *GetAssetPath(const char *path)
|
||||
{
|
||||
if (path && path[0] == '.' && path[1] == '/') {
|
||||
path += 2;
|
||||
while (*path == '/') {
|
||||
++path;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
bool Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode)
|
||||
{
|
||||
SDL_assert(puserdata != NULL);
|
||||
@@ -1882,11 +1904,12 @@ bool Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mo
|
||||
|
||||
if (!asset_manager) {
|
||||
Internal_Android_Create_AssetManager();
|
||||
if (!asset_manager) {
|
||||
return SDL_SetError("Couldn't create asset manager");
|
||||
}
|
||||
}
|
||||
|
||||
if (!asset_manager) {
|
||||
return SDL_SetError("Couldn't create asset manager");
|
||||
}
|
||||
fileName = GetAssetPath(fileName);
|
||||
|
||||
asset = AAssetManager_open(asset_manager, fileName, AASSET_MODE_UNKNOWN);
|
||||
if (!asset) {
|
||||
@@ -1944,6 +1967,8 @@ bool Android_JNI_EnumerateAssetDirectory(const char *path, SDL_EnumerateDirector
|
||||
}
|
||||
}
|
||||
|
||||
path = GetAssetPath(path);
|
||||
|
||||
AAssetDir *adir = AAssetManager_openDir(asset_manager, path);
|
||||
if (!adir) {
|
||||
return SDL_SetError("AAssetManager_openDir failed");
|
||||
@@ -1969,6 +1994,8 @@ bool Android_JNI_GetAssetPathInfo(const char *path, SDL_PathInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
path = GetAssetPath(path);
|
||||
|
||||
// this is sort of messy, but there isn't a stat()-like interface to the Assets.
|
||||
AAsset *aasset = AAssetManager_open(asset_manager, path, AASSET_MODE_UNKNOWN);
|
||||
if (aasset) { // it's a file!
|
||||
|
||||
@@ -27,19 +27,26 @@
|
||||
|
||||
// This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source, slightly modified to work with FreeBSD
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/kbio.h>
|
||||
#include <sys/consio.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "SDL_evdev_kbd_default_keyaccmap.h"
|
||||
|
||||
#ifndef K_OFF
|
||||
#define K_OFF 0x04
|
||||
#endif
|
||||
|
||||
typedef void(fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard State
|
||||
*/
|
||||
@@ -48,6 +55,7 @@ struct SDL_EVDEV_keyboard_state
|
||||
{
|
||||
int console_fd;
|
||||
int keyboard_fd;
|
||||
bool muted;
|
||||
unsigned long old_kbd_mode;
|
||||
unsigned short **key_maps;
|
||||
keymap_t *key_map;
|
||||
@@ -63,6 +71,10 @@ struct SDL_EVDEV_keyboard_state
|
||||
char shift_state;
|
||||
char text[128];
|
||||
unsigned int text_len;
|
||||
void (*vt_release_callback)(void *);
|
||||
void *vt_release_callback_data;
|
||||
void (*vt_acquire_callback)(void *);
|
||||
void *vt_acquire_callback_data;
|
||||
};
|
||||
|
||||
static bool SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
|
||||
@@ -83,22 +95,28 @@ static int fatal_signals[] = {
|
||||
SIGSYS
|
||||
};
|
||||
|
||||
static void kbd_cleanup(void)
|
||||
static void vt_update_mouse(SDL_EVDEV_keyboard_state *kbd, int operation)
|
||||
{
|
||||
struct mouse_info mData;
|
||||
|
||||
SDL_zero(mData);
|
||||
mData.operation = operation;
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
}
|
||||
|
||||
static void kbd_cleanup(void)
|
||||
{
|
||||
SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state;
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = NULL;
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_SHOW;
|
||||
ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
if (kbd->keyboard_fd != kbd->console_fd) {
|
||||
close(kbd->keyboard_fd);
|
||||
}
|
||||
ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index));
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
vt_update_mouse(kbd, true);
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_reraise_signal(int sig)
|
||||
@@ -220,15 +238,108 @@ static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd)
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
VT_SIGNAL_NONE,
|
||||
VT_SIGNAL_RELEASE,
|
||||
VT_SIGNAL_ACQUIRE,
|
||||
};
|
||||
static int vt_release_signal;
|
||||
static int vt_acquire_signal;
|
||||
static SDL_AtomicInt vt_signal_pending;
|
||||
SDL_AtomicInt vt_current;
|
||||
|
||||
typedef void (*signal_handler)(int signum);
|
||||
|
||||
|
||||
static void kbd_vt_release_signal_action(int signum)
|
||||
{
|
||||
SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_RELEASE);
|
||||
SDL_SetAtomicInt(&vt_current, VT_THEIRS);
|
||||
}
|
||||
|
||||
static void kbd_vt_acquire_signal_action(int signum)
|
||||
{
|
||||
SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_ACQUIRE);
|
||||
SDL_SetAtomicInt(&vt_current, VT_OURS);
|
||||
}
|
||||
|
||||
static bool setup_vt_signal(int signum, signal_handler handler)
|
||||
{
|
||||
struct sigaction *old_action_p;
|
||||
struct sigaction new_action;
|
||||
old_action_p = &(old_sigaction[signum]);
|
||||
SDL_zero(new_action);
|
||||
new_action.sa_handler = handler;
|
||||
new_action.sa_flags = SA_RESTART;
|
||||
if (sigaction(signum, &new_action, old_action_p) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (old_action_p->sa_handler != SIG_DFL) {
|
||||
// This signal is already in use
|
||||
if (signum == SIGUSR1 || signum == SIGUSR2) {
|
||||
/*
|
||||
* For the moment we have no other options in FreeBSD because
|
||||
* the vt(4) will not accept signal numbers over 32.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
sigaction(signum, old_action_p, NULL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void kbd_vt_quit(int console_fd)
|
||||
{
|
||||
struct vt_mode mode;
|
||||
|
||||
if (vt_release_signal) {
|
||||
sigaction(vt_release_signal, &old_sigaction[vt_release_signal], NULL);
|
||||
vt_release_signal = 0;
|
||||
}
|
||||
if (vt_acquire_signal) {
|
||||
sigaction(vt_acquire_signal, &old_sigaction[vt_acquire_signal], NULL);
|
||||
vt_acquire_signal = 0;
|
||||
}
|
||||
|
||||
SDL_zero(mode);
|
||||
mode.mode = VT_AUTO;
|
||||
ioctl(console_fd, VT_SETMODE, &mode);
|
||||
}
|
||||
|
||||
static bool kbd_vt_init(int console_fd)
|
||||
{
|
||||
struct vt_mode mode;
|
||||
|
||||
if (setup_vt_signal(SIGUSR1, kbd_vt_release_signal_action)) {
|
||||
vt_release_signal = SIGUSR1;
|
||||
}
|
||||
if (setup_vt_signal(SIGUSR2, kbd_vt_acquire_signal_action)) {
|
||||
vt_acquire_signal = SIGUSR2;
|
||||
}
|
||||
if (!vt_release_signal || !vt_acquire_signal ) {
|
||||
kbd_vt_quit(console_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_zero(mode);
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = vt_release_signal;
|
||||
mode.acqsig = vt_acquire_signal;
|
||||
mode.frsig = SIGIO;
|
||||
if (ioctl(console_fd, VT_SETMODE, &mode) < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Failed VT_SETMODE ioctl: %s", strerror(errno));
|
||||
kbd_vt_quit(console_fd);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
|
||||
{
|
||||
SDL_EVDEV_keyboard_state *kbd;
|
||||
struct mouse_info mData;
|
||||
char flag_state;
|
||||
char *devicePath;
|
||||
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_HIDE;
|
||||
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(SDL_EVDEV_keyboard_state));
|
||||
if (!kbd) {
|
||||
return NULL;
|
||||
@@ -246,7 +357,6 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
|
||||
kbd->kbInfo = SDL_calloc(1, sizeof(keyboard_info_t));
|
||||
|
||||
ioctl(kbd->console_fd, KDGKBINFO, kbd->kbInfo);
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
|
||||
if (ioctl(kbd->console_fd, KDGKBSTATE, &flag_state) == 0) {
|
||||
kbd->ledflagstate = flag_state;
|
||||
@@ -265,43 +375,31 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
|
||||
kbd->key_map = &keymap_default_us_acc;
|
||||
}
|
||||
|
||||
if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) {
|
||||
/* Take keyboard from console and open the actual keyboard device.
|
||||
* Ensures that the keystrokes do not leak through to the console.
|
||||
*/
|
||||
ioctl(kbd->console_fd, CONS_RELKBD, 1ul);
|
||||
SDL_asprintf(&devicePath, "/dev/kbd%d", kbd->kbInfo->kb_index);
|
||||
kbd->keyboard_fd = open(devicePath, O_WRONLY | O_CLOEXEC);
|
||||
if (kbd->keyboard_fd == -1) {
|
||||
// Give keyboard back.
|
||||
ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index));
|
||||
kbd->keyboard_fd = kbd->console_fd;
|
||||
}
|
||||
if (!kbd_vt_init(kbd->console_fd)) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "kbd_vt_init failed");
|
||||
}
|
||||
|
||||
/* Make sure to restore keyboard if application fails to call
|
||||
* SDL_Quit before exit or fatal signal is raised.
|
||||
*/
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) {
|
||||
kbd_register_emerg_cleanup(kbd);
|
||||
}
|
||||
SDL_free(devicePath);
|
||||
} else
|
||||
kbd->keyboard_fd = kbd->console_fd;
|
||||
kbd->keyboard_fd = kbd->console_fd;
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) {
|
||||
kbd_register_emerg_cleanup(kbd);
|
||||
}
|
||||
}
|
||||
|
||||
vt_update_mouse(kbd, MOUSE_HIDE);
|
||||
|
||||
return kbd;
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
struct mouse_info mData;
|
||||
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_SHOW;
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
|
||||
kbd_vt_quit(kbd->console_fd);
|
||||
|
||||
vt_update_mouse(kbd, MOUSE_SHOW);
|
||||
|
||||
kbd_unregister_emerg_cleanup();
|
||||
|
||||
@@ -322,14 +420,83 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||
|
||||
void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted)
|
||||
{
|
||||
struct termios tios;
|
||||
|
||||
SDL_zero(tios);
|
||||
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (muted == state->muted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tcgetattr(state->console_fd, &tios) == -1) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Could not get terminal mode: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (muted) {
|
||||
if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) {
|
||||
ioctl(state->console_fd, KDSKBMODE, K_OFF);
|
||||
cfmakeraw(&tios);
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) {
|
||||
kbd_register_emerg_cleanup(state);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kbd_unregister_emerg_cleanup();
|
||||
|
||||
cfmakesane(&tios);
|
||||
ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode);
|
||||
}
|
||||
|
||||
if (tcsetattr(state->console_fd, TCSAFLUSH, &tios) == -1) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Could not set terminal mode to %s: %s", muted ? "raw" : "sane", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
state->muted = muted;
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void *), void *release_callback_data, void (*acquire_callback)(void *), void *acquire_callback_data)
|
||||
{
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->vt_release_callback = release_callback;
|
||||
state->vt_release_callback_data = release_callback_data;
|
||||
state->vt_acquire_callback = acquire_callback;
|
||||
state->vt_acquire_callback_data = acquire_callback_data;
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state)
|
||||
{
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
int signal_pending = SDL_GetAtomicInt(&vt_signal_pending);
|
||||
|
||||
if (signal_pending != VT_SIGNAL_NONE) {
|
||||
if (signal_pending == VT_SIGNAL_RELEASE) {
|
||||
if (state->vt_release_callback) {
|
||||
vt_update_mouse(state, MOUSE_SHOW);
|
||||
state->vt_release_callback(state->vt_release_callback_data);
|
||||
}
|
||||
ioctl(state->console_fd, VT_RELDISP, 1);
|
||||
} else {
|
||||
if (state->vt_acquire_callback) {
|
||||
state->vt_acquire_callback(state->vt_acquire_callback_data);
|
||||
vt_update_mouse(state, MOUSE_HIDE);
|
||||
}
|
||||
ioctl(state->console_fd, VT_RELDISP, VT_ACKACQ);
|
||||
}
|
||||
SDL_CompareAndSwapAtomicInt(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -329,6 +329,11 @@ void SDL_EVDEV_Poll(void)
|
||||
|
||||
for (item = _this->first; item; item = item->next) {
|
||||
while ((len = read(item->fd, events, sizeof(events))) > 0) {
|
||||
#ifdef SDL_INPUT_FBSDKBIO
|
||||
if (SDL_GetAtomicInt(&vt_current) == VT_THEIRS) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
len /= sizeof(events[0]);
|
||||
for (i = 0; i < len; ++i) {
|
||||
struct input_event *event = &events[i];
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
#ifndef SDL_evdev_kbd_h_
|
||||
#define SDL_evdev_kbd_h_
|
||||
|
||||
#ifdef SDL_INPUT_FBSDKBIO
|
||||
enum {
|
||||
VT_OURS,
|
||||
VT_THEIRS,
|
||||
};
|
||||
extern SDL_AtomicInt vt_current;
|
||||
#endif
|
||||
|
||||
struct SDL_EVDEV_keyboard_state;
|
||||
typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state;
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ static const char *GetAppName(void)
|
||||
if (exe_name) {
|
||||
return exe_name;
|
||||
}
|
||||
|
||||
return "SDL_App";
|
||||
}
|
||||
|
||||
@@ -244,7 +243,7 @@ static bool FcitxCreateInputContext(SDL_DBusContext *dbus, const char *appname,
|
||||
DBusMessageIter args, array, sub;
|
||||
dbus->message_iter_init_append(msg, &args);
|
||||
dbus->message_iter_open_container(&args, DBUS_TYPE_ARRAY, "(ss)", &array);
|
||||
dbus->message_iter_open_container(&array, DBUS_TYPE_STRUCT, 0, &sub);
|
||||
dbus->message_iter_open_container(&array, DBUS_TYPE_STRUCT, NULL, &sub);
|
||||
dbus->message_iter_append_basic(&sub, DBUS_TYPE_STRING, &program);
|
||||
dbus->message_iter_append_basic(&sub, DBUS_TYPE_STRING, &appname);
|
||||
dbus->message_iter_close_container(&array, &sub);
|
||||
|
||||
@@ -49,17 +49,23 @@ static char *GetDBUSObjectPath(void)
|
||||
|
||||
// Ensure it starts with a letter or underscore
|
||||
if (!SDL_isalpha(app_id[0]) && app_id[0] != '_') {
|
||||
app_id = SDL_realloc(app_id, SDL_strlen(app_id) + 2);
|
||||
if (!app_id) {
|
||||
return NULL;
|
||||
}
|
||||
SDL_memmove(app_id + 1, app_id, SDL_strlen(app_id) + 1);
|
||||
app_id[0] = '_';
|
||||
}
|
||||
|
||||
// Create full path
|
||||
char path[1024];
|
||||
SDL_snprintf(path, sizeof(path), "/org/libsdl/%s_%d", app_id, getpid());
|
||||
char *path;
|
||||
if (SDL_asprintf(&path, "/org/libsdl/%s_%d", app_id, getpid()) < 0) {
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
SDL_free(app_id);
|
||||
|
||||
return SDL_strdup(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
static char *GetAppDesktopPath(void)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "SDL_evdev_capabilities.h"
|
||||
#include "../unix/SDL_poll.h"
|
||||
|
||||
#define SDL_UDEV_FALLBACK_LIBS "libudev.so.1", "libudev.so.0"
|
||||
#define SDL_UDEV_FALLBACK_LIBS "libudev.so.1", "libudev.so.0"
|
||||
|
||||
static const char *SDL_UDEV_LIBS[] = { SDL_UDEV_FALLBACK_LIBS };
|
||||
|
||||
@@ -247,22 +247,19 @@ bool SDL_UDEV_GetProductInfo(const char *device_path, struct input_id *inpid, in
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stat(device_path, &statbuf) == -1) {
|
||||
if (stat(device_path, &statbuf) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (S_ISBLK(statbuf.st_mode)) {
|
||||
type = 'b';
|
||||
}
|
||||
else if (S_ISCHR(statbuf.st_mode)) {
|
||||
} else if (S_ISCHR(statbuf.st_mode)) {
|
||||
type = 'c';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
dev = _this->syms.udev_device_new_from_devnum(_this->udev, type, statbuf.st_rdev);
|
||||
|
||||
if (!dev) {
|
||||
return false;
|
||||
}
|
||||
@@ -302,6 +299,45 @@ bool SDL_UDEV_GetProductInfo(const char *device_path, struct input_id *inpid, in
|
||||
return true;
|
||||
}
|
||||
|
||||
char *SDL_UDEV_GetProductSerial(const char *device_path)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char type;
|
||||
struct udev_device *dev;
|
||||
const char *val;
|
||||
char *result = NULL;
|
||||
|
||||
if (!_this) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (stat(device_path, &statbuf) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (S_ISBLK(statbuf.st_mode)) {
|
||||
type = 'b';
|
||||
} else if (S_ISCHR(statbuf.st_mode)) {
|
||||
type = 'c';
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev = _this->syms.udev_device_new_from_devnum(_this->udev, type, statbuf.st_rdev);
|
||||
if (!dev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_SERIAL_SHORT");
|
||||
if (val && *val) {
|
||||
result = SDL_strdup(val);
|
||||
}
|
||||
|
||||
_this->syms.udev_device_unref(dev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SDL_UDEV_UnloadLibrary(void)
|
||||
{
|
||||
if (!_this) {
|
||||
|
||||
@@ -105,6 +105,7 @@ extern bool SDL_UDEV_LoadLibrary(void);
|
||||
extern void SDL_UDEV_Poll(void);
|
||||
extern bool SDL_UDEV_Scan(void);
|
||||
extern bool SDL_UDEV_GetProductInfo(const char *device_path, struct input_id *inpid, int *class, char **driver);
|
||||
extern char *SDL_UDEV_GetProductSerial(const char *device_path);
|
||||
extern bool SDL_UDEV_AddCallback(SDL_UDEV_Callback cb);
|
||||
extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb);
|
||||
extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void);
|
||||
|
||||
@@ -36,13 +36,13 @@ bool NGAGE_IsClassicModel()
|
||||
return (0x101f8c19 == phone_id);
|
||||
}
|
||||
|
||||
void NGAGE_printf(const char *fmt, ...)
|
||||
void NGAGE_DebugPrintf(const char *fmt, ...)
|
||||
{
|
||||
char buffer[512] = { 0 };
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buffer, fmt, ap);
|
||||
(void)SDL_vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
TBuf<512> buf;
|
||||
@@ -51,21 +51,6 @@ void NGAGE_printf(const char *fmt, ...)
|
||||
RDebug::Print(_L("%S"), &buf);
|
||||
}
|
||||
|
||||
void NGAGE_vnprintf(char *buf, size_t size, const char *fmt, va_list ap)
|
||||
{
|
||||
char buffer[512] = { 0 };
|
||||
|
||||
vsprintf(buffer, fmt, ap);
|
||||
|
||||
TBuf<512> tbuf;
|
||||
tbuf.Copy(TPtrC8((TText8 *)buffer));
|
||||
|
||||
RDebug::Print(_L("%S"), &tbuf);
|
||||
|
||||
strncpy(buf, buffer, size - 1);
|
||||
buf[size - 1] = '\0';
|
||||
}
|
||||
|
||||
TInt NGAGE_GetFreeHeapMemory()
|
||||
{
|
||||
TInt free = 0;
|
||||
|
||||
@@ -28,6 +28,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
bool NGAGE_IsClassicModel();
|
||||
void NGAGE_DebugPrintf(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -64,6 +64,11 @@ static gulong signal_connect(gpointer instance, const gchar *detailed_signal, vo
|
||||
|
||||
static void QuitGtk(void)
|
||||
{
|
||||
if (sdl_main_context) {
|
||||
gtk.g.main_context_unref(sdl_main_context);
|
||||
sdl_main_context = NULL;
|
||||
}
|
||||
|
||||
SDL_UnloadObject(libgdk);
|
||||
SDL_UnloadObject(libgtk);
|
||||
|
||||
@@ -137,12 +142,13 @@ static bool InitGtk(void)
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_push_thread_default);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_pop_thread_default);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_new);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_unref);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_acquire);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_iteration);
|
||||
|
||||
gtk.g.signal_connect = signal_connect;
|
||||
|
||||
if (gtk.gtk.init_check(0, NULL) == GTK_FALSE) {
|
||||
if (gtk.gtk.init_check(NULL, NULL) == GTK_FALSE) {
|
||||
QuitGtk();
|
||||
return SDL_SetError("Could not init GTK");
|
||||
}
|
||||
@@ -192,7 +198,6 @@ void SDL_Gtk_Quit(void)
|
||||
|
||||
QuitGtk();
|
||||
SDL_zero(gtk);
|
||||
sdl_main_context = NULL;
|
||||
|
||||
SDL_SetInitialized(>k_init, false);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ typedef struct SDL_GtkContext
|
||||
void (*main_context_push_thread_default)(GMainContext *context);
|
||||
void (*main_context_pop_thread_default)(GMainContext *context);
|
||||
GMainContext *(*main_context_new)(void);
|
||||
void (*main_context_unref)(GMainContext *context);
|
||||
gboolean (*main_context_acquire)(GMainContext *context);
|
||||
gboolean (*main_context_iteration)(GMainContext *context, gboolean may_block);
|
||||
} g;
|
||||
|
||||
76
src/core/unix/SDL_libthai.c
Normal file
76
src/core/unix/SDL_libthai.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef HAVE_LIBTHAI_H
|
||||
|
||||
#include "SDL_libthai.h"
|
||||
|
||||
#ifdef SDL_LIBTHAI_DYNAMIC
|
||||
SDL_ELF_NOTE_DLOPEN(
|
||||
"Thai",
|
||||
"Thai language support",
|
||||
SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
SDL_LIBTHAI_DYNAMIC
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
SDL_LibThai *SDL_LibThai_Create(void)
|
||||
{
|
||||
SDL_LibThai *th;
|
||||
|
||||
th = (SDL_LibThai *)SDL_malloc(sizeof(SDL_LibThai));
|
||||
if (!th) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_LIBTHAI_DYNAMIC
|
||||
#define SDL_LIBTHAI_LOAD_SYM(a, x, n, t) x = ((t)SDL_LoadFunction(a->lib, n)); if (!x) { SDL_UnloadObject(a->lib); SDL_free(a); return NULL; }
|
||||
|
||||
th->lib = SDL_LoadObject(SDL_LIBTHAI_DYNAMIC);
|
||||
if (!th->lib) {
|
||||
SDL_free(th);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_LIBTHAI_LOAD_SYM(th, th->make_cells, "th_make_cells", SDL_LibThaiMakeCells);
|
||||
#else
|
||||
th->make_cells = th_make_cells;
|
||||
#endif
|
||||
|
||||
return th;
|
||||
}
|
||||
|
||||
void SDL_LibThai_Destroy(SDL_LibThai *th)
|
||||
{
|
||||
if (!th) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SDL_LIBTHAI_DYNAMIC
|
||||
SDL_UnloadObject(th->lib);
|
||||
#endif
|
||||
|
||||
SDL_free(th);
|
||||
}
|
||||
|
||||
#endif
|
||||
43
src/core/unix/SDL_libthai.h
Normal file
43
src/core/unix/SDL_libthai.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_libthai_h_
|
||||
#define SDL_libthai_h_
|
||||
|
||||
#ifdef HAVE_LIBTHAI_H
|
||||
#include <thai/thcell.h>
|
||||
|
||||
typedef size_t (*SDL_LibThaiMakeCells)(const thchar_t *s, size_t, struct thcell_t cells[], size_t *, int);
|
||||
|
||||
typedef struct SDL_LibThai {
|
||||
SDL_SharedObject *lib;
|
||||
|
||||
SDL_LibThaiMakeCells make_cells;
|
||||
} SDL_LibThai;
|
||||
|
||||
extern SDL_LibThai *SDL_LibThai_Create(void);
|
||||
extern void SDL_LibThai_Destroy(SDL_LibThai *th);
|
||||
|
||||
#endif // HAVE_LIBTHAI_H
|
||||
|
||||
#endif // SDL_libthai_h_
|
||||
@@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid, SDL_AudioFormat force_format)
|
||||
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid, SDL_AudioFormat force_format, bool supports_recording_playback_devices)
|
||||
{
|
||||
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
|
||||
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
|
||||
@@ -147,7 +147,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn
|
||||
|
||||
if (!device) {
|
||||
// handle is freed by SDL_IMMDevice_FreeDeviceHandle!
|
||||
SDL_IMMDevice_HandleData *handle = (SDL_IMMDevice_HandleData *)SDL_malloc(sizeof(SDL_IMMDevice_HandleData));
|
||||
SDL_IMMDevice_HandleData *handle = (SDL_IMMDevice_HandleData *)SDL_calloc(1, sizeof(*handle));
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn
|
||||
SDL_free(handle);
|
||||
return NULL;
|
||||
}
|
||||
SDL_memcpy(&handle->directsound_guid, dsoundguid, sizeof(GUID));
|
||||
SDL_copyp(&handle->directsound_guid, dsoundguid);
|
||||
|
||||
SDL_AudioSpec spec;
|
||||
SDL_zero(spec);
|
||||
@@ -165,6 +165,28 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn
|
||||
spec.format = (force_format != SDL_AUDIO_UNKNOWN) ? force_format : SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
|
||||
|
||||
device = SDL_AddAudioDevice(recording, devname, &spec, handle);
|
||||
|
||||
if (!recording && supports_recording_playback_devices) {
|
||||
// handle is freed by SDL_IMMDevice_FreeDeviceHandle!
|
||||
SDL_IMMDevice_HandleData *recording_handle = (SDL_IMMDevice_HandleData *)SDL_malloc(sizeof(*recording_handle));
|
||||
if (!recording_handle) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
recording_handle->immdevice_id = SDL_wcsdup(devid);
|
||||
if (!recording_handle->immdevice_id) {
|
||||
SDL_free(recording_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_copyp(&recording_handle->directsound_guid, dsoundguid);
|
||||
|
||||
if (!SDL_AddAudioDevice(true, devname, &spec, recording_handle)) {
|
||||
SDL_free(recording_handle->immdevice_id);
|
||||
SDL_free(recording_handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (!device) {
|
||||
SDL_free(handle->immdevice_id);
|
||||
SDL_free(handle);
|
||||
@@ -184,6 +206,7 @@ typedef struct SDLMMNotificationClient
|
||||
const IMMNotificationClientVtbl *lpVtbl;
|
||||
SDL_AtomicInt refcount;
|
||||
SDL_AudioFormat force_format;
|
||||
bool supports_recording_playback_devices;
|
||||
} SDLMMNotificationClient;
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_QueryInterface(IMMNotificationClient *client, REFIID iid, void **ppv)
|
||||
@@ -257,7 +280,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM
|
||||
GUID dsoundguid;
|
||||
GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid);
|
||||
if (utf8dev) {
|
||||
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid, client->force_format);
|
||||
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid, client->force_format, client->supports_recording_playback_devices);
|
||||
SDL_free(utf8dev);
|
||||
}
|
||||
} else {
|
||||
@@ -288,7 +311,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = {
|
||||
SDLMMNotificationClient_OnPropertyValueChanged
|
||||
};
|
||||
|
||||
static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 }, SDL_AUDIO_UNKNOWN };
|
||||
static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 }, SDL_AUDIO_UNKNOWN, false };
|
||||
|
||||
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks)
|
||||
{
|
||||
@@ -365,7 +388,23 @@ bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool reco
|
||||
return true;
|
||||
}
|
||||
|
||||
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device, SDL_AudioFormat force_format)
|
||||
bool SDL_IMMDevice_GetIsCapture(IMMDevice *device)
|
||||
{
|
||||
bool iscapture = false;
|
||||
IMMEndpoint *endpoint = NULL;
|
||||
if (SUCCEEDED(IMMDevice_QueryInterface(device, &SDL_IID_IMMEndpoint, (void **)&endpoint))) {
|
||||
EDataFlow flow;
|
||||
|
||||
if (SUCCEEDED(IMMEndpoint_GetDataFlow(endpoint, &flow))) {
|
||||
iscapture = (flow == eCapture);
|
||||
}
|
||||
}
|
||||
|
||||
IMMEndpoint_Release(endpoint);
|
||||
return iscapture;
|
||||
}
|
||||
|
||||
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device, SDL_AudioFormat force_format, bool supports_recording_playback_devices)
|
||||
{
|
||||
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
|
||||
...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */
|
||||
@@ -407,7 +446,7 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
|
||||
SDL_zero(dsoundguid);
|
||||
GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid);
|
||||
if (devname) {
|
||||
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid, force_format);
|
||||
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid, force_format, supports_recording_playback_devices);
|
||||
if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) {
|
||||
*default_device = sdldevice;
|
||||
}
|
||||
@@ -424,12 +463,13 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
|
||||
IMMDeviceCollection_Release(collection);
|
||||
}
|
||||
|
||||
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording, SDL_AudioFormat force_format)
|
||||
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording, SDL_AudioFormat force_format, bool supports_recording_playback_devices)
|
||||
{
|
||||
EnumerateEndpointsForFlow(false, default_playback, force_format);
|
||||
EnumerateEndpointsForFlow(true, default_recording, force_format);
|
||||
EnumerateEndpointsForFlow(false, default_playback, force_format, supports_recording_playback_devices);
|
||||
EnumerateEndpointsForFlow(true, default_recording, force_format, supports_recording_playback_devices);
|
||||
|
||||
notification_client.force_format = force_format;
|
||||
notification_client.supports_recording_playback_devices = supports_recording_playback_devices;
|
||||
|
||||
// if this fails, we just won't get hotplug events. Carry on anyhow.
|
||||
IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)¬ification_client);
|
||||
|
||||
@@ -37,7 +37,8 @@ typedef struct SDL_IMMDevice_callbacks
|
||||
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks);
|
||||
void SDL_IMMDevice_Quit(void);
|
||||
bool SDL_IMMDevice_Get(struct SDL_AudioDevice *device, IMMDevice **immdevice, bool recording);
|
||||
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording, SDL_AudioFormat force_format);
|
||||
bool SDL_IMMDevice_GetIsCapture(IMMDevice* device);
|
||||
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording, SDL_AudioFormat force_format, bool supports_recording_playback_devices);
|
||||
LPGUID SDL_IMMDevice_GetDirectSoundGUID(struct SDL_AudioDevice *device);
|
||||
LPCWSTR SDL_IMMDevice_GetDevID(struct SDL_AudioDevice *device);
|
||||
void SDL_IMMDevice_FreeDeviceHandle(struct SDL_AudioDevice *device);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "../../video/SDL_surface_c.h"
|
||||
|
||||
#include <shellapi.h> // CommandLineToArgvW()
|
||||
|
||||
#include <objbase.h> // for CoInitialize/CoUninitialize (Win32 only)
|
||||
#ifdef HAVE_ROAPI_H
|
||||
#include <roapi.h> // For RoInitialize/RoUninitialize (Win32 only)
|
||||
@@ -284,6 +286,36 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||
}
|
||||
|
||||
static DWORD WIN_BuildNumber = 0;
|
||||
static BOOL IsWindowsBuildVersionAtLeast(DWORD dwBuildNumber)
|
||||
{
|
||||
if (WIN_BuildNumber != 0) {
|
||||
return (WIN_BuildNumber >= dwBuildNumber);
|
||||
}
|
||||
|
||||
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
|
||||
if (!ntdll) {
|
||||
return false;
|
||||
}
|
||||
// There is no function to get Windows build number, so let's get it here via RtlGetVersion
|
||||
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion");
|
||||
NT_OSVERSIONINFOW os_info;
|
||||
os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW);
|
||||
os_info.dwBuildNumber = 0;
|
||||
if (RtlGetVersionFunc) {
|
||||
RtlGetVersionFunc(&os_info);
|
||||
}
|
||||
FreeLibrary(ntdll);
|
||||
|
||||
WIN_BuildNumber = (os_info.dwBuildNumber & ~0xF0000000);
|
||||
return (WIN_BuildNumber >= dwBuildNumber);
|
||||
}
|
||||
#else
|
||||
static BOOL IsWindowsBuildVersionAtLeast(DWORD dwBuildNumber)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// apply some static variables so we only call into the Win32 API once per process for each check.
|
||||
@@ -300,6 +332,24 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO
|
||||
return result;
|
||||
#endif
|
||||
|
||||
BOOL WIN_IsWine(void)
|
||||
{
|
||||
static bool checked;
|
||||
static bool is_wine;
|
||||
|
||||
if (!checked) {
|
||||
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
|
||||
if (ntdll) {
|
||||
if (GetProcAddress(ntdll, "wine_get_version") != NULL) {
|
||||
is_wine = true;
|
||||
}
|
||||
FreeLibrary(ntdll);
|
||||
}
|
||||
checked = true;
|
||||
}
|
||||
return is_wine;
|
||||
}
|
||||
|
||||
// this is the oldest thing we run on (and we may lose support for this in SDL3 at any time!),
|
||||
// so there's no "OrGreater" as that would always be TRUE. The other functions are here to
|
||||
// ask "can we support a specific feature?" but this function is here to ask "do we need to do
|
||||
@@ -324,6 +374,11 @@ BOOL WIN_IsWindows8OrGreater(void)
|
||||
CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0));
|
||||
}
|
||||
|
||||
BOOL WIN_IsWindows11OrGreater(void)
|
||||
{
|
||||
return IsWindowsBuildVersionAtLeast(22000);
|
||||
}
|
||||
|
||||
#undef CHECKWINVER
|
||||
|
||||
|
||||
@@ -441,21 +496,7 @@ bool WIN_WindowRectValid(const RECT *rect)
|
||||
void WIN_UpdateDarkModeForHWND(HWND hwnd)
|
||||
{
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
|
||||
if (!ntdll) {
|
||||
return;
|
||||
}
|
||||
// There is no function to get Windows build number, so let's get it here via RtlGetVersion
|
||||
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion");
|
||||
NT_OSVERSIONINFOW os_info;
|
||||
os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW);
|
||||
os_info.dwBuildNumber = 0;
|
||||
if (RtlGetVersionFunc) {
|
||||
RtlGetVersionFunc(&os_info);
|
||||
}
|
||||
FreeLibrary(ntdll);
|
||||
os_info.dwBuildNumber &= ~0xF0000000;
|
||||
if (os_info.dwBuildNumber < 17763) {
|
||||
if (!IsWindowsBuildVersionAtLeast(17763)) {
|
||||
// Too old to support dark mode
|
||||
return;
|
||||
}
|
||||
@@ -466,7 +507,7 @@ void WIN_UpdateDarkModeForHWND(HWND hwnd)
|
||||
RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(104));
|
||||
ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(132));
|
||||
AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(133));
|
||||
if (os_info.dwBuildNumber < 18362) {
|
||||
if (!IsWindowsBuildVersionAtLeast(18362)) {
|
||||
AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
|
||||
if (AllowDarkModeForAppFunc) {
|
||||
AllowDarkModeForAppFunc(true);
|
||||
@@ -491,7 +532,7 @@ void WIN_UpdateDarkModeForHWND(HWND hwnd)
|
||||
value = (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) ? TRUE : FALSE;
|
||||
}
|
||||
FreeLibrary(uxtheme);
|
||||
if (os_info.dwBuildNumber < 18362) {
|
||||
if (!IsWindowsBuildVersionAtLeast(18362)) {
|
||||
SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), SDL_reinterpret_cast(HANDLE, SDL_static_cast(INT_PTR, value)));
|
||||
} else {
|
||||
HMODULE user32 = GetModuleHandle(TEXT("user32.dll"));
|
||||
@@ -616,4 +657,72 @@ int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr,
|
||||
return WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
|
||||
}
|
||||
|
||||
const char *WIN_CheckDefaultArgcArgv(int *pargc, char ***pargv, void **pallocated)
|
||||
{
|
||||
// If the provided argv is valid, we pass it to the main function as-is, since it's probably what the user wants.
|
||||
// Otherwise, we take a NULL argv as an instruction for SDL to parse the command line into an argv.
|
||||
// On Windows, when SDL provides the main entry point, argv is always NULL.
|
||||
|
||||
const char *out_of_mem_str = "Out of memory - aborting";
|
||||
const char *proc_err_str = "Error processing command line arguments - aborting";
|
||||
|
||||
*pallocated = NULL;
|
||||
|
||||
if (*pargv) {
|
||||
return NULL; // just go with what was provided, no error message.
|
||||
}
|
||||
|
||||
// We need to be careful about how we allocate/free memory here. We can't use SDL_alloc()/SDL_free()
|
||||
// because the application might have used SDL_SetMemoryFunctions() to change the allocator.
|
||||
LPWSTR *argvw = NULL;
|
||||
char **argv = NULL;
|
||||
|
||||
const LPWSTR command_line = GetCommandLineW();
|
||||
|
||||
// Because of how the Windows command line is structured, we know for sure that the buffer size required to
|
||||
// store all argument strings converted to UTF-8 (with null terminators) is guaranteed to be less than or equal
|
||||
// to the size of the original command line string converted to UTF-8.
|
||||
const int argdata_size = WideCharToMultiByte(CP_UTF8, 0, command_line, -1, NULL, 0, NULL, NULL); // Includes the null terminator
|
||||
if (!argdata_size) {
|
||||
return proc_err_str;
|
||||
}
|
||||
|
||||
int argc = -1;
|
||||
argvw = CommandLineToArgvW(command_line, &argc);
|
||||
if (!argvw || argc < 0) {
|
||||
return out_of_mem_str;
|
||||
}
|
||||
|
||||
// Allocate argv followed by the argument string buffer as one contiguous allocation.
|
||||
argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv) + argdata_size);
|
||||
if (!argv) {
|
||||
LocalFree(argvw);
|
||||
return out_of_mem_str;
|
||||
}
|
||||
|
||||
char *argdata = ((char *)argv) + (argc + 1) * sizeof(*argv);
|
||||
int argdata_index = 0;
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
const int bytes_written = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argdata + argdata_index, argdata_size - argdata_index, NULL, NULL);
|
||||
if (!bytes_written) {
|
||||
HeapFree(GetProcessHeap(), 0, argv);
|
||||
LocalFree(argvw);
|
||||
return proc_err_str;
|
||||
}
|
||||
argv[i] = argdata + argdata_index;
|
||||
argdata_index += bytes_written;
|
||||
}
|
||||
|
||||
argv[argc] = NULL;
|
||||
|
||||
LocalFree(argvw);
|
||||
|
||||
*pargc = argc;
|
||||
*pallocated = argv;
|
||||
*pargv = argv;
|
||||
|
||||
return NULL; // no error string.
|
||||
}
|
||||
|
||||
#endif // defined(SDL_PLATFORM_WINDOWS)
|
||||
|
||||
@@ -168,6 +168,9 @@ extern void WIN_CoUninitialize(void);
|
||||
extern HRESULT WIN_RoInitialize(void);
|
||||
extern void WIN_RoUninitialize(void);
|
||||
|
||||
// Returns true if we're running on Wine
|
||||
extern BOOL WIN_IsWine(void);
|
||||
|
||||
// Returns true if we're running on Windows XP (any service pack). DOES NOT CHECK XP "OR GREATER"!
|
||||
extern BOOL WIN_IsWindowsXP(void);
|
||||
|
||||
@@ -180,6 +183,9 @@ extern BOOL WIN_IsWindows7OrGreater(void);
|
||||
// Returns true if we're running on Windows 8 and newer
|
||||
extern BOOL WIN_IsWindows8OrGreater(void);
|
||||
|
||||
// Returns true if we're running on Windows 11 and newer
|
||||
extern BOOL WIN_IsWindows11OrGreater(void);
|
||||
|
||||
// You need to SDL_free() the result of this call.
|
||||
extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid);
|
||||
|
||||
@@ -203,6 +209,9 @@ extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat);
|
||||
// WideCharToMultiByte, but with some WinXP management.
|
||||
extern int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);
|
||||
|
||||
// parse out command lines from OS if argv is NULL, otherwise pass through unchanged. `*pallocated` must be HeapFree'd by caller if not NULL on successful return. Returns NULL on success, error string on problems.
|
||||
const char *WIN_CheckDefaultArgcArgv(int *pargc, char ***pargv, void **pallocated);
|
||||
|
||||
// Ends C function definitions when using C++
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user