Compare commits

...

99 Commits

Author SHA1 Message Date
Ozkan Sezer
f0e7000f92 alsa: fix signatures of snd_pcm_info_free and snd_pcm_hw_params_get_rate
Reference issue: https://github.com/libsdl-org/SDL/issues/13845.
2025-09-02 17:02:32 +03:00
Ozkan Sezer
d2ab01b8bb openslES: really fix build.. 2025-09-01 20:38:37 +03:00
Ozkan Sezer
f5246d0181 openslES: fix build 2025-09-01 20:25:28 +03:00
Ryan C. Gordon
b8c802632b openslES: OpenSL ES on Android only supports two formats, limit to that.
(Three with the floating point extension, which we use.)

This is according to:

https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android

Previously, this would accept a request for Sint8 or Sint32 and disaster
would ensue.

Fixes #13779.

(cherry picked from commit 0b2a003a35)
(cherry picked from commit 7323104f97)
2025-09-01 11:37:10 -04:00
Ozkan Sezer
1725d6b049 regenerate configure script. 2025-08-31 20:20:04 +03:00
Gleb Mazovetskiy
5ed21d1ccb configure.ac: Fix AC_DEFINE HAVE_LIBUSB
Fixes an error with autoconf 2.72
2025-08-31 09:36:24 -07:00
Ozkan Sezer
7a34e14c8e SDL_hidapi.c: fix -Wundef failures due to HAVE_DRIVER_BACKEND check 2025-08-30 14:33:32 +03:00
Ozkan Sezer
1a8e667f3d CI: add OpenBSD workflow
(backported from commit c0e5fd55d2)
2025-08-30 14:23:40 +03:00
Frank Praznik
d31d98d436 wayland: Add a sigtimedwait() implementation for OpenBSD
sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it. Add a replacement implementation based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation

(backported from commit 1049426a76)
2025-08-30 14:23:04 +03:00
Ozkan Sezer
56d43ee296 update config.guess and config.sub from git://git.sv.gnu.org/config.git 2025-08-28 11:22:50 +03:00
Chase Knowlden
1f21aae242 Update NDK version to 28 (#13729)
* Update NDK version to 28 and add 16kb page size linker flags to x86_64

* Remove Android Linker Options

16kb page size is now the default since NDK r28c

* Update Android CI to use NDK 28

(cherry picked from commit 6e422e5ff2)
2025-08-13 15:13:18 +02:00
Sam Lantinga
5e85a29e75 Support the "ambient" value for SDL_HINT_AUDIO_CATEGORY
Fixes https://github.com/libsdl-org/SDL/issues/13732

(cherry picked from commit 4725213eef)
2025-08-12 09:54:57 -07:00
Anonymous Maarten
f201b64ffe release: build aarch64 libraries with 16kiB page size 2025-08-09 05:25:31 +02:00
Sam Lantinga
4f9723ece7 Revert "autotools, android: Support Google Play 16 KB Page Size Requirement"
This reverts commit e7489a0931.

If you need to support the Google Play 16 kiB page size requirement, the recommendation is to use NDK r28c or newer, which automatically aligns binaries correctly.
2025-08-07 11:38:29 -07:00
Sam Lantinga
53dbe1862e Revert "Support Google Play 16 KB Page Size Requirement (#13470)"
This reverts commit 4b2aa3f102.

If you need to support the Google Play 16 kiB page size requirement, the recommendation is to use NDK r28c or newer, which automatically aligns binaries correctly.
2025-08-07 11:38:24 -07:00
Ozkan Sezer
e7489a0931 autotools, android: Support Google Play 16 KB Page Size Requirement
autotools port of commit 4b2aa3f102.
2025-08-07 20:10:02 +03:00
Anonymous Maarten
4b2aa3f102 Support Google Play 16 KB Page Size Requirement (#13470)
- See: https://developer.android.com/guide/practices/page-sizes#update-packaging
- Also, make min API uniform at 21 (from 16 and 23 in a few places)

Manual backport of dc2c83c383
2025-08-07 17:59:05 +02:00
Ryan C. Gordon
272b073323 SDL_enabled_assert(): Use NULL istead of 0 to explicity initialize the pointer members of SDL_AssertData
(cherry picked from commit faf3bd9991)
2025-08-03 13:40:12 -04:00
SDL Wiki Bot
d310b5679f Sync SDL2 wiki -> header
[ci skip]
2025-07-30 03:15:25 +00:00
Ryan C. Gordon
afc1d9122b pipewire: Report correct device default formats instead of hardcoding Float32.
The comment in the source wasn't true; PipeWire doesn't _have_ to work in
float format. It presumably does if it has to mix, but if a game is the only
thing making noise on the system--a common scenario--then it might be able to
pass, say, Sint16 data straight through to the hardware without conversion.

Fixes #12129.

(cherry picked from commit 943c4abcb4)
2025-07-29 18:21:01 -04:00
Sam Lantinga
af2279b286 Revert "Use SDL_MessageBoxFlags and SDL_MessageBoxButtonFlags appropriately"
This reverts commit 059af5265a.
2025-07-29 09:41:35 -07:00
Sam Lantinga
059af5265a Use SDL_MessageBoxFlags and SDL_MessageBoxButtonFlags appropriately
(cherry picked from commit 991d28ae37)
2025-07-29 09:38:52 -07:00
Dan Andrus
e610529e84 Check NSWindow::isVisible before sending SDL_WINDOWEVENT_RESTORED during Cocoa_WindowListener::windowDidResize 2025-07-28 14:46:55 -04:00
Ozkan Sezer
74df61530f autotools, cmake: fix the sys/audioio.h checks.
Reference issue: https://github.com/libsdl-org/SDL/issues/13405.
2025-07-28 12:40:30 +03:00
Boris I. Bendovsky
3c36718348 [SDL2] Implement SDL_GL_GetAttribute for SDL_GL_FLOATBUFFERS 2025-07-27 19:55:57 -07:00
Anonymous Maarten
b36252b120 ci+n3ds: avoid apt-get package manager
- use Unix Makefiles (with parallelization) CMake generator
- use binutils strings binary from devkitpro

( Manual backport of commit e6d200e51c )
2025-07-27 23:50:02 +03:00
Ozkan Sezer
ead4a032d3 sun audio: remove ifdefs, always include sys/audioio.h and sys/ioctl.h 2025-07-27 00:10:02 +03:00
Ryan C. Gordon
cf1eb95fb1 sunaudio: don't compile in the sun audio backend if sys/audioio.h is missing.
Newer Solaris-based releases, like OpenIndiana, don't include this, using
Open Sound System, or something layered over OSS like PulseAudio, instead.

Fixes #13405.
2025-07-26 13:50:20 -04:00
vanfanel
34691de22b SDL2: Fill the SDL_AudioSpec in add_device() 2025-07-20 23:47:25 -04:00
vanfanel
874ca5a678 SDL2: Add missing symbol loading for SDL_GetDefaultAudioInfo() implementation on ALSA. 2025-07-17 13:08:52 -04:00
vanfanel
8d5984464e SDL2: Implement SDL_GetDefaultAudioInfo() on the ALSA backend. 2025-07-17 13:08:52 -04:00
Ryan C. Gordon
2a6baf50e9 include: Added some basic documentation so SDL_KeyCode shows up on the wiki.
Fixes #11525.
2025-07-14 00:33:32 -04:00
Yorick Reum
6c9c2a9ac2 Xcode-iOS/Demos/src/fireworks.c: Make rendering CPU efficient 2025-07-12 07:35:08 -07:00
Anonymous Maarten
8605624158 ci: build MSVC release binary on windows-2025 2025-07-12 13:08:31 +02:00
Ryan C. Gordon
b537380065 cocoa: Patched to compile. 2025-07-10 16:27:47 -04:00
Ryan C. Gordon
b2c3e6fade cocoa: Don't use trick of briefly focusing the Dock on newer macOS releases.
On newer systems, the trick isn't necessary, and if you do it, if the user is
moving the mouse when launching the app, it'll show a hidden Dock.

Fixes #10340.

(manually backported from SDL3 from commit 279dabfc96)
2025-07-10 15:57:55 -04:00
Wouter Wijsman
309d1481a4 PSP: Truncate thread name when passing to sceKernelCreateThread 2025-07-09 17:11:32 +02:00
Ozkan Sezer
2fb6abb9ad fix ARM64 linkage with Visual Studio >= 17.14 when SDL_LIBC is disabled
Reference issue:  https://github.com/libsdl-org/SDL/issues/13254
2025-07-08 14:50:10 +03:00
Ryan C. Gordon
cd0cf8b855 SDL_audio.h: tweak SDL_OpenAudioDevice() docs to fix a weird wordwrap issue.
Fixes https://github.com/libsdl-org/sdlwiki/pull/816.

("Fixes.")
2025-07-01 13:38:16 -04:00
evgenydrainov
2bc3ec44b1 keyboard: Add reference to SDL_Keymod in the comments 2025-06-24 07:36:22 -07:00
Mitch Cairns
e4475d1868 Fixed Nintendo Switch thumbstick calibration
(cherry picked from commit 3a6f9e01f8)
2025-06-22 15:29:12 -07:00
Sam Lantinga
6a71328638 Fixed Nintendo Switch Pro thumbstick calibration
Fixes https://github.com/libsdl-org/SDL/issues/13246

(cherry picked from commit 038a3806eb)
2025-06-21 20:06:08 -07:00
Wohlstand
6701f938f7 Vita Render: Limit the scope of cliprect to viewport
Don't allow cliprect be larger than viewport's scope
2025-06-20 13:15:57 -07:00
Wohlstand
1c09a7117a Vita: Fixed absence of clipping when viewport is set
#13034
2025-06-20 13:15:57 -07:00
ceski
9eb50a906a Read Switch controller gyro/accel sensitivity coeffs (SDL2)
These vary by controller, so using the stored values should improve the accuracy of the sensor data.
2025-06-13 12:18:12 -07:00
SDL Wiki Bot
027d46f03a Sync SDL2 wiki -> header
[ci skip]
2025-06-13 17:09:05 +00:00
Son Phan Trung
3416296366 README-touch.md: fix header separators 2025-06-06 08:28:10 -07:00
Wes Lord
01c3ccd541 Move comment in .wikiheaders-options to own line
Was not parsing correctly, causing an error
2025-06-02 07:21:42 -04:00
Ryan C. Gordon
3c08172d06 Revert "opengles2: Restore previous default texture_formats."
This reverts commit 9f7ccbe8d4.

Fixes #13109.
2025-06-01 03:21:36 -04:00
Francisco Javier Trujillo Mata
d0c2d8bc40 Fix wrong callback type
(cherry picked from commit c89357bf60)
2025-05-20 11:11:47 -07:00
Sam Lantinga
33eb167da8 Fixed rare crash trying to interrupt SDL_WaitEvent()
Fixes https://github.com/libsdl-org/SDL/issues/12797

(cherry picked from commit 992e4c59bd)
2025-05-19 14:24:26 -07:00
Joe [ReRezd]
4b4f6b3e22 Fix: GameCube controller adapter hotplug not working
SDL_PrivateJoystickAdded was called before setting the InstanceId in the adapters ctx->joysticks array.  This would eventually broadcast the SDL_EVENT_JOYSTICK_ADDED event with the new InstanceId, if your program listens for the added events and opens joysticks at that point it would always fail because there would be no matching InstanceId in the ctx->joysticks array.

(cherry picked from commit afd1e51023)
2025-05-19 08:26:25 -07:00
Sam Lantinga
2163887f29 Define illegal_instruction() when it will be actually used
(cherry picked from commit 29d2116495)
2025-05-08 12:53:33 -07:00
Sam Clegg
c0f78dee5e [emscripten] Remove reference to Module['createContext']
Backported from https://github.com/libsdl-org/SDL/pull/12970
2025-05-06 14:46:19 -07:00
A. Wilcox
17e6208c1b cpuinfo: Use auxv for AltiVec on Linux if possible
The SIGILL handler is not very reliable and can cause crashes.

Linux provides the CPU's AltiVec support status in getauxval.

(cherry picked from commit 7490471796)
2025-05-04 13:55:59 -07:00
Ozkan Sezer
157f894d5d don't prototype strdup() for __clang_analyzer__ case in windows builds.
Fixes:  https://github.com/libsdl-org/SDL/issues/12948.
(cherry picked from commit 17bba029ba)
2025-05-04 20:47:28 +03:00
Derek Schuff
a220e7c422 Port #12581 to SDL2
This fixes undefined behavior resulting from adding offsets to nullptr.
2025-05-01 21:36:23 -07:00
Sam Lantinga
2442c85cb8 Call IOHIDDeviceClose() if needed in hid_close() on macOS
Unregistering the input report callback marks the device as disconnected, so IOHIDDeviceClose() would never be called if the device wasn't already disconnected  when hid_close() was called.

Fixes https://github.com/libsdl-org/SDL/issues/12255
2025-04-29 11:21:26 -07:00
Sam Lantinga
5b951141d2 Revert "Don't leak device handle in macOS 10.10 or newer"
This reverts commit 5925c27efb.

Fixes https://github.com/libsdl-org/SDL/issues/12807
2025-04-29 11:07:29 -07:00
Cameron Gutman
15fd3fcdc2 events: Fix undefined behavior when disabling some event types
Shifting a signed int left by 31 is UB.
2025-04-29 00:30:41 -05:00
Sam Lantinga
45b01d16b1 Fixed reliability of initializing Switch controllers on macOS
It looks like both macOS (15.1.1) and SDL are trying to talk to the controller at the same time, which can cause interleaved replies or even locking up the controller. Waiting a bit before talking to the controller seems to take care of this.
2025-04-28 20:21:53 -07:00
SternXD
433810c58d SDL2: Update from Visual Studio 2019 to Visual Studio 2022 2025-04-22 20:59:26 -07:00
SDL Wiki Bot
916ddb1ef8 Sync SDL2 wiki -> header
[ci skip]
2025-04-22 21:18:56 +00:00
Sam Lantinga
1c75cb4f8a Revert "Sync SDL2 wiki -> header"
This reverts commit 26e946ef08.

Stop it Skynet!
2025-04-22 14:17:22 -07:00
SDL Wiki Bot
26e946ef08 Sync SDL2 wiki -> header
[ci skip]
2025-04-22 17:22:42 +00:00
Petar Popovic
035518d065 SDL_BlitSurface() comment: only dstrect is modified in function 2025-04-22 10:22:27 -07:00
Boris I. Bendovsky
40b1eac541 [SDL2] Fix using of DXSDK_DIR in older CMake
- Remove duplicate 'dollar' symbol in the path
- Use command 'file' to normalize file paths
2025-04-22 10:12:01 -07:00
Ozkan Sezer
bfab0a968f SDL_cpuinfo.h: only include immintrin.h for x86 targets.
Reference issue: https://github.com/libsdl-org/SDL_image/issues/537
Reference issue: https://github.com/libsdl-org/SDL_mixer/issues/648
2025-04-03 18:55:04 +03:00
Sam Lantinga
f0a8e09f7c Skip the Jack audio server test
The Jack server might not be running even though the libraries are installed.
2025-03-30 21:31:38 -07:00
SDL Wiki Bot
2e4c12cd2c Sync SDL2 wiki -> header
[ci skip]
2025-03-27 19:20:39 +00:00
Sam Lantinga
3e47181800 Default SDL_HINT_ACCELEROMETER_AS_JOYSTICK to 0 on Linux
The Linux joystick driver supports associating sensor devices with the related controller device, so enable that by default.

Fixes https://github.com/libsdl-org/SDL/issues/12043
2025-03-25 09:07:10 -07:00
Anonymous Maarten
8436ce98b4 tests: port failing SDL_Renderer test from pysdl2 to testautomation 2025-03-21 00:55:52 +01:00
Carl Åstholm
a8f0eb4c33 emscripten: Don't use legacy JS library functions for assertions
(cherry picked from commit 54f5b73333)
2025-03-20 16:36:02 -07:00
Anonymous Maarten
069eb012aa tests: port failing SDL subsystem test from pysdl2 to testautomation 2025-03-20 20:30:18 +01:00
Anonymous Maarten
7d8a6f1603 tests: port failing SDL_Renderer test from pysdl2 to testautomation 2025-03-20 20:30:18 +01:00
Dragon-Baroque
d63b3376a4 The posix4 library has been merged into the libc library
Backported from commit 07e4dea693.
Reference issue: https://github.com/libsdl-org/SDL/issues/12588.
2025-03-20 09:47:20 +03:00
Sam Lantinga
52146cf067 Fixed raw input device GUIDs changing randomly between runs
On Windows 11, apparently HidD_GetManufacturerString() and HidD_GetProductString() can return TRUE without actually filling in any string data.

Fixes https://github.com/libsdl-org/SDL/issues/12566

(cherry picked from commit 4fc9509ab7)
2025-03-17 13:57:35 -07:00
Sam Lantinga
46a51b4298 Fixed crash if info->path is NULL
(cherry picked from commit 715301cef5)
2025-03-17 09:47:53 -07:00
Anonymous Maarten
4f488b9be2 tests: port failing window test from pysdl2 to testautomation 2025-03-16 18:15:16 -07:00
Anonymous Maarten
f48a96a976 test: actually run rect tests 2025-03-14 21:40:31 +01:00
Anonymous Maarten
39bb71c442 tests: port failing SDL_Rect tests from pysdl2 to testautomation 2025-03-14 17:29:27 +01:00
Anonymous Maarten
177fb9cb6c tests: port failing SDL_Hint tests from pysdl2 to testautomation 2025-03-14 17:29:27 +01:00
SDL Wiki Bot
fc536dcb7e Sync SDL2 wiki -> header
[ci skip]
2025-03-12 19:23:45 +00:00
Sam Lantinga
1caae3e9e4 Fixed sscanf("026", "%1x%1x%1x", &r, &g, &b)
Fixes https://github.com/libsdl-org/SDL/issues/12510

(cherry picked from commit be6ed6e9c4)
2025-03-10 15:45:31 -07:00
SDL Wiki Bot
22a87a22ca Sync SDL2 wiki -> header
[ci skip]
2025-03-07 17:02:06 +00:00
Neal Gompa
6be87ceb33 pipewire: Ensure that the correct struct is used for enumeration APIs
PipeWire now requires the correct struct type is used, otherwise
it will fail to compile.

Reference: 188d920733

Fixes: https://github.com/libsdl-org/SDL/issues/12224
(cherry picked from commit d35bef64e9)
2025-03-06 14:36:44 -05:00
Sam Lantinga
ab44451578 Added support for the "%n" sscanf format specifier
(cherry picked from commit 6980325310)
2025-02-25 08:07:33 -08:00
SDL Wiki Bot
52ac07d327 Sync SDL2 wiki -> header
[ci skip]
2025-02-25 15:55:15 +00:00
Tomasz Pakuła
0809be4ec5 [SDL2] Add SDL_HINT_JOYSTICK_HAPTIC_AXES
Allows users to overwrite the number of haptic axes defined for a given
joystick. Also supports a "wildcard" VID:PID of 0xFFFF/0xFFFF
2025-02-25 07:54:59 -08:00
Petter Reinholdtsen
24693ac285 Changed PULSEAUDIO_FlushRecording() to only flush audio present when called.
When the flushing is not able to keep up with the audio stream coming in,
it will end up flushing forever and block API clients from getting any audio.

Fixes #9706
2025-02-24 07:31:06 -08:00
Cameron Gutman
92cadaf917 keyboard: Fix comment regarding implicit calls to SDL_StartTextInput()
It was always done inside SDL_VideoInit().
2025-02-23 19:00:32 -06:00
Anonymous Maarten
d2eb72fd14 ci: drop classic Intel compiler
1) The classic Intel compiler is depreated in favor of the oneapi compiler
2) SPA_FALLTHROUGH is used in pipewire's spa/utils/json.h, and causes build errors
2025-02-23 21:26:10 +01:00
Anonymous Maarten
b4d733619a ci: GitHub is retiring Ubuntu 20.04 support
backport of 8d3db06ff2
2025-02-23 19:45:27 +01:00
Anonymous Maarten
ed2c004c8a ci: clang32 on msys2 is EOL
backport of 70f657e520
2025-02-23 19:40:38 +01:00
Paper
6421f12d7f thread/windows: fix stack overflow in exception naming
(cherry picked from commit 1a853973ab)
2025-02-20 08:20:41 -08:00
Ozkan Sezer
ee49025f80 dynapi: use DosScanEnv() for os/2. 2025-02-20 11:50:04 +03:00
Sam Lantinga
5925c27efb Don't leak device handle in macOS 10.10 or newer
Merged upstream fix for macOS:
cdc473dfe4

In one of the early versions of macOS, when you try to close the device
with IOHIDDeviceClose() that is being physically disconnected.
Starting with some version of macOS, this crash bug was fixed,
and starting with macSO 10.15 the opposite effect took place:
in some environments crash happens if IOHIDDeviceClose() is _not_ called.

This patch is to keep a workaround for old versions of macOS,
and don't have a leak in new/tested environments.

Fixes https://github.com/libsdl-org/SDL/issues/12255
2025-02-19 16:55:03 -08:00
Sam Clegg
aa00738a21 Fix SDL_emscriptenaudio.c under wasm64
Verified locally by running `browser64.test_sdl2_mixer_wav` in
emscripten.
2025-02-18 13:53:58 -08:00
Sam Lantinga
5330041ea9 Updated to version 2.33.0 for development 2025-02-08 09:15:11 -08:00
79 changed files with 1539 additions and 395 deletions

View File

@@ -28,7 +28,6 @@ class JobOs(Enum):
WindowsLatest = "windows-latest"
UbuntuLatest = "ubuntu-latest"
MacosLatest = "macos-latest"
Ubuntu20_04 = "ubuntu-20.04"
Ubuntu22_04 = "ubuntu-22.04"
Ubuntu24_04 = "ubuntu-24.04"
Macos13 = "macos-13"
@@ -51,19 +50,18 @@ class SdlPlatform(Enum):
Riscos = "riscos"
FreeBSD = "freebsd"
NetBSD = "netbsd"
OpenBSD = "openbsd"
Watcom = "watcom"
class Msys2Platform(Enum):
Mingw32 = "mingw32"
Mingw64 = "mingw64"
Clang32 = "clang32"
Clang64 = "clang64"
Ucrt64 = "ucrt64"
class IntelCompiler(Enum):
Icc = "icc"
Icx = "icx"
@@ -107,7 +105,6 @@ class JobSpec:
JOB_SPECS = {
"msys2-mingw32": JobSpec(name="Windows (msys2, mingw32)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw32", msys2_platform=Msys2Platform.Mingw32, ),
"msys2-mingw64": JobSpec(name="Windows (msys2, mingw64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64", msys2_platform=Msys2Platform.Mingw64, ),
"msys2-clang32": JobSpec(name="Windows (msys2, clang32)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw32-clang", msys2_platform=Msys2Platform.Clang32, ),
"msys2-clang64": JobSpec(name="Windows (msys2, clang64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64-clang", msys2_platform=Msys2Platform.Clang64, ),
"msys2-ucrt64": JobSpec(name="Windows (msys2, ucrt64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64-ucrt", msys2_platform=Msys2Platform.Ucrt64, ),
"msvc-x64": JobSpec(name="Windows (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-x64", msvc_arch=MsvcArch.X64, msvc_project="VisualC/SDL.sln", ),
@@ -120,11 +117,9 @@ JOB_SPECS = {
"msvc-arm64": JobSpec(name="Windows (MSVC, ARM64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-arm64", msvc_arch=MsvcArch.Arm64, ),
"msvc-uwp-x64": JobSpec(name="UWP (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-UWP", msvc_arch=MsvcArch.X64, msvc_project="VisualC-WinRT/SDL-UWP.sln", uwp=True, ),
"msvc-gdk-x64": JobSpec(name="GDK (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-GDK", msvc_arch=MsvcArch.X64, msvc_project="VisualC-GDK/SDL.sln", gdk=True, no_cmake=True, ),
"ubuntu-20.04": JobSpec(name="Ubuntu 20.04", os=JobOs.Ubuntu20_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu20.04", autotools=True),
"ubuntu-22.04": JobSpec(name="Ubuntu 22.04", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04", autotools=True),
"steamrt-sniper": JobSpec(name="Steam Linux Runtime (Sniper)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-slrsniper", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta", ),
"ubuntu-intel-icx": JobSpec(name="Ubuntu 20.04 (Intel oneAPI)", os=JobOs.Ubuntu20_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu20.04-oneapi", intel=IntelCompiler.Icx, ),
"ubuntu-intel-icc": JobSpec(name="Ubuntu 20.04 (Intel Compiler)", os=JobOs.Ubuntu20_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu20.04-icc", intel=IntelCompiler.Icc, ),
"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, ),
"macos-gnu-arm64-x64": JobSpec(name="MacOS (GNU prefix)", os=JobOs.MacosLatest, platform=SdlPlatform.MacOS, artifact="SDL-macos-arm64-x64-gnu",autotools=True, apple_archs={AppleArch.X86_64, AppleArch.ARM64, }, ),
"ios": JobSpec(name="iOS (CMake & xcode)", os=JobOs.MacosLatest, platform=SdlPlatform.Ios, artifact="SDL-ios-arm64", xcode=True, ),
"tvos": JobSpec(name="tvOS (CMake & xcode)", os=JobOs.MacosLatest, platform=SdlPlatform.Tvos, artifact="SDL-tvos-arm64", xcode=True, ),
@@ -139,6 +134,7 @@ JOB_SPECS = {
"vita-pvr": JobSpec(name="Sony PlayStation Vita (GLES w/ PVR_PSP2)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Vita, artifact="SDL-vita-pvr", container="vitasdk/vitasdk:latest", vita_gles=VitaGLES.Pvr, ),
"riscos": JobSpec(name="RISC OS", os=JobOs.UbuntuLatest, platform=SdlPlatform.Riscos, artifact="SDL-riscos", container="riscosdotinfo/riscos-gccsdk-4.7:latest", ),
"netbsd": JobSpec(name="NetBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.NetBSD, artifact="SDL-netbsd-x64", autotools=True, ),
"openbsd": JobSpec(name="OpenBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.OpenBSD, artifact="SDL-openbsd-x64", autotools=True, ),
"freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", autotools=True, ),
"watcom-win32": JobSpec(name="Watcom (Windows)", os=JobOs.WindowsLatest, platform=SdlPlatform.Watcom, artifact="SDL-watcom-win32", no_cmake=True, watcom_platform=WatcomPlatform.Windows ),
"watcom-os2": JobSpec(name="Watcom (OS/2)", os=JobOs.WindowsLatest, platform=SdlPlatform.Watcom, artifact="SDL-watcom-win32", no_cmake=True, watcom_platform=WatcomPlatform.OS2 ),
@@ -181,6 +177,7 @@ class JobDetails:
brew_packages: list[str] = dataclasses.field(default_factory=list)
cmake_toolchain_file: str = ""
cmake_arguments: list[str] = dataclasses.field(default_factory=list)
cmake_generator: str = "Ninja"
cmake_build_arguments: list[str] = dataclasses.field(default_factory=list)
cppflags: list[str] = dataclasses.field(default_factory=list)
cc: str = ""
@@ -226,6 +223,7 @@ class JobDetails:
setup_vita_gles_type: str = ""
check_sources: bool = False
watcom_makefile: str = ""
binutils_strings: str = "strings"
def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
data = {
@@ -259,6 +257,7 @@ class JobDetails:
"cflags": my_shlex_join(self.cppflags + self.cflags),
"cxxflags": my_shlex_join(self.cppflags + self.cxxflags),
"ldflags": my_shlex_join(self.ldflags),
"cmake-generator": self.cmake_generator,
"cmake-toolchain-file": self.cmake_toolchain_file,
"cmake-arguments": my_shlex_join(self.cmake_arguments),
"cmake-build-arguments": my_shlex_join(self.cmake_build_arguments),
@@ -291,6 +290,7 @@ class JobDetails:
"setup-gdk-folder": self.setup_gdk_folder,
"check-sources": self.check_sources,
"watcom-makefile": self.watcom_makefile,
"binutils-strings": self.binutils_strings,
}
return {k: v for k, v in data.items() if v != ""}
@@ -344,10 +344,6 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
case IntelCompiler.Icx:
job.cc = "icx"
job.cxx = "icpx"
case IntelCompiler.Icc:
job.cc = "icc"
job.cxx = "icpc"
job.cppflags.append("-diag-disable=10441")
case _:
raise ValueError(f"Invalid intel={spec.intel}")
job.source_cmd = f"source /opt/intel/oneapi/setvars.sh;"
@@ -610,11 +606,14 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
case SdlPlatform.N3ds:
job.cmake_generator = "Unix Makefiles"
job.cmake_build_arguments.append("-j$(nproc)")
job.shared = False
job.apt_packages = ["ninja-build", "binutils"]
job.apt_packages = []
job.run_tests = False
job.cc_from_cmake = True
job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
job.binutils_strings = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-strings"
job.static_lib = StaticLibType.A
case SdlPlatform.Msys2:
job.shell = "msys2 {0}"
@@ -627,7 +626,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
"clang64": "mingw-w64-clang-x86_64",
"ucrt64": "mingw-w64-ucrt-x86_64",
}[spec.msys2_platform.value]
job.msys2_no_perl = spec.msys2_platform in (Msys2Platform.Mingw32, Msys2Platform.Clang32)
job.msys2_no_perl = spec.msys2_platform in (Msys2Platform.Mingw32, )
job.shared_lib = SharedLibType.WIN32
job.static_lib = StaticLibType.A
case SdlPlatform.Riscos:
@@ -646,7 +645,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
))
job.cmake_toolchain_file = "/home/riscos/env/toolchain-riscos.cmake"
job.static_lib = StaticLibType.A
case SdlPlatform.FreeBSD | SdlPlatform.NetBSD:
case SdlPlatform.FreeBSD | SdlPlatform.NetBSD | SdlPlatform.OpenBSD:
job.build_autotools_tests = False
job.cpactions = True
job.no_cmake = True
@@ -671,6 +670,12 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
job.cpactions_arch = "x86-64"
job.cpactions_setup_cmd = "export PATH=\"/usr/pkg/sbin:/usr/pkg/bin:/sbin:$PATH\"; export PKG_CONFIG_PATH=\"/usr/pkg/lib/pkgconfig\";export PKG_PATH=\"https://cdn.netBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f \"1 2\" -d.)/All/\";echo \"PKG_PATH=$PKG_PATH\";echo \"uname -a -> \"$(uname -a)\"\";sudo -E sysctl -w security.pax.aslr.enabled=0;sudo -E sysctl -w security.pax.aslr.global=0;sudo -E pkgin clean;sudo -E pkgin update"
job.cpactions_install_cmd = "sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1"
case SdlPlatform.OpenBSD:
job.cpactions_os = "openbsd"
job.cpactions_version = "7.4"
job.cpactions_arch = "x86-64"
job.cpactions_setup_cmd = "sudo pkg_add -u"
job.cpactions_install_cmd = "sudo pkg_add cmake ninja pkgconf wayland wayland-protocols xwayland libxkbcommon libinotify pulseaudio dbus ibus"
case SdlPlatform.Watcom:
match spec.watcom_platform:
case WatcomPlatform.OS2:

View File

@@ -177,7 +177,7 @@ jobs:
#shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -GNinja \
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -G "${{ matrix.platform.cmake-generator }}" \
-Wdeprecated -Wdev -Werror \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-DSDL_WERROR=${{ matrix.platform.werror }} \
@@ -207,9 +207,9 @@ jobs:
run: |
echo "This should show us the SDL_REVISION"
echo "Shared library:"
${{ (matrix.platform.shared-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
${{ (matrix.platform.shared-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
echo "Static library:"
${{ (matrix.platform.static-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
${{ (matrix.platform.static-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
- name: 'Run build-time tests (CMake)'
id: cmake-tests
if: ${{ !matrix.platform.no-cmake && matrix.platform.run-tests }}

View File

@@ -181,7 +181,7 @@ jobs:
msvc:
needs: [src]
runs-on: windows-2019
runs-on: windows-2025
outputs:
VC-x86: ${{ steps.releaser.outputs.VC-x86 }}
VC-x64: ${{ steps.releaser.outputs.VC-x64 }}

View File

@@ -23,7 +23,8 @@ manpageheaderfiletext = Defined in %fname%
# A handful of others we fix up in the header itself with /* WIKI CATEGORY: x */ comments.
headercategoryeval = s/\ASDL_config_.*?\.h\Z//; s/\ASDL_test_.*?\.h\Z//; s/\ASDL_?(.*?)\.h\Z/$1/; ucfirst();
quickrefenabled = 0 # !!! FIXME: maybe later, but there are probably documentation gaps to fix first.
# !!! FIXME: maybe later, but there are probably documentation gaps to fix first.
quickrefenabled = 0
quickrefcategoryorder = Init,Hints,Error,Version,Properties,Log,Video,Events,Keyboard,Mouse,Touch,Gesture,GameController,Joystick,Haptic,Audio,Timer,Render,LoadSO,Thread,Mutex,Atomic,Filesystem,RWOPS,Pixels,Surface,Blendmode,Rect,Clipboard,Messagebox,Vulkan,Metal,Platform,Power,Sensor,Bits,Endian,Assert,CPUInfo,Locale,System,Misc,GUID,Main,Stdinc
quickreftitle = SDL2 API Quick Reference
quickrefurl = https://libsdl.org/

View File

@@ -88,7 +88,7 @@ endif()
# See docs/release_checklist.md
set(SDL_MAJOR_VERSION 2)
set(SDL_MINOR_VERSION 32)
set(SDL_MINOR_VERSION 33)
set(SDL_MICRO_VERSION 0)
set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
@@ -755,6 +755,11 @@ if(MSVC)
if(MSVC_VERSION GREATER 1926 AND CMAKE_GENERATOR_PLATFORM MATCHES "Win32|x64")
list(APPEND EXTRA_LDFLAGS_BUILD "-CETCOMPAT")
endif()
# for VS >= 17.14 targeting ARM64: inline the Interlocked funcs
if(MSVC_VERSION GREATER 1943 AND SDL_CPU_ARM64 AND NOT SDL_LIBC)
list(APPEND EXTRA_CFLAGS /forceInterlockedFunctions-)
endif()
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
@@ -1094,6 +1099,7 @@ if(SDL_LIBC)
endforeach()
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
check_symbol_exists(sigtimedwait "signal.h" HAVE_SIGTIMEDWAIT)
check_symbol_exists(setjmp "setjmp.h" HAVE_SETJMP)
check_symbol_exists(nanosleep "time.h" HAVE_NANOSLEEP)
check_symbol_exists(sysconf "unistd.h" HAVE_SYSCONF)
@@ -1465,10 +1471,14 @@ elseif(EMSCRIPTEN)
elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
if(SDL_AUDIO)
if(SYSV5 OR SOLARIS OR HPUX)
set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
file(GLOB SUN_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/sun/*.c)
list(APPEND SOURCE_FILES ${SUN_AUDIO_SOURCES})
set(HAVE_SDL_AUDIO TRUE)
# Newer Solaris-based systems, like OpenIndiana, don't have this interface anymore. Check for the header first.
check_include_file(sys/audioio.h HAVE_SYS_AUDIOIO_H)
if(HAVE_SYS_AUDIOIO_H)
set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
file(GLOB SUN_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/sun/*.c)
list(APPEND SOURCE_FILES ${SUN_AUDIO_SOURCES})
set(HAVE_SDL_AUDIO TRUE)
endif()
elseif(NETBSD)
set(SDL_AUDIO_DRIVER_NETBSD 1)
file(GLOB NETBSD_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/netbsd/*.c)
@@ -1829,8 +1839,10 @@ elseif(WINDOWS)
set(HAVE_DIRECTX TRUE)
if(NOT MINGW AND NOT USE_WINSDK_DIRECTX)
# TODO: change $ENV{DXSDL_DIR} to get the path from the include checks
target_link_directories(sdl-build-options INTERFACE "$$ENV{DXSDK_DIR}\\lib\\${PROCESSOR_ARCH}")
target_include_directories(sdl-build-options INTERFACE "$ENV{DXSDK_DIR}\\Include")
file(TO_CMAKE_PATH "$ENV{DXSDK_DIR}\\lib\\${PROCESSOR_ARCH}" SDL2_TMP_DXSDK_LIB_DIR)
target_link_directories(sdl-build-options INTERFACE "${SDL2_TMP_DXSDK_LIB_DIR}")
file(TO_CMAKE_PATH "$ENV{DXSDK_DIR}\\Include" SDL2_TMP_DXSDK_INCLUDE_DIR)
target_include_directories(sdl-build-options INTERFACE "${SDL2_TMP_DXSDK_INCLUDE_DIR}")
endif()
endif()
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})

View File

@@ -14,7 +14,7 @@
LIBNAME = SDL2
MAJOR_VERSION = 2
MINOR_VERSION = 32
MINOR_VERSION = 33
MICRO_VERSION = 0
VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
DESCRIPTION = Simple DirectMedia Layer 2

View File

@@ -5,7 +5,7 @@
LIBNAME = SDL2
MAJOR_VERSION = 2
MINOR_VERSION = 32
MINOR_VERSION = 33
MICRO_VERSION = 0
VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)

View File

@@ -371,6 +371,7 @@
<TargetPlatformVersion>10.0.16299.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.0.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -391,7 +392,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -603,4 +604,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@@ -456,7 +456,10 @@ main(int argc, char *argv[])
while (!done) {
SDL_Event event;
double deltaTime = updateDeltaTime();
SDL_bool hasEvents = SDL_FALSE;
while (SDL_PollEvent(&event)) {
hasEvents = SDL_TRUE;
if (event.type == SDL_QUIT) {
done = 1;
}
@@ -466,10 +469,17 @@ main(int argc, char *argv[])
spawnEmitterParticle(x, y);
}
}
stepParticles(deltaTime);
drawParticles();
SDL_GL_SwapWindow(window);
SDL_Delay(1);
/* Only update and render if we have active particles or just received events */
if (num_active_particles > 0 || hasEvents) {
stepParticles(deltaTime);
drawParticles();
SDL_GL_SwapWindow(window);
SDL_Delay(16); // Target 60 FPS when active
} else {
/* Idle state - wait for events with longer delay to save CPU */
SDL_Delay(100); // Much longer delay when idle
}
}
/* delete textures */

View File

@@ -19,10 +19,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.32.0</string>
<string>2.33.0</string>
<key>CFBundleSignature</key>
<string>SDLX</string>
<key>CFBundleVersion</key>
<string>2.32.0</string>
<string>2.33.0</string>
</dict>
</plist>

View File

@@ -9728,8 +9728,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 3201.0.0;
DYLIB_CURRENT_VERSION = 3201.0.0;
DYLIB_COMPATIBILITY_VERSION = 3301.0.0;
DYLIB_CURRENT_VERSION = 3301.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
@@ -9770,7 +9770,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_LINK_OBJC_RUNTIME = NO;
MARKETING_VERSION = 2.32.0;
MARKETING_VERSION = 2.33.0;
OTHER_LDFLAGS = "-liconv";
};
name = Release;
@@ -9813,8 +9813,8 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 3201.0.0;
DYLIB_CURRENT_VERSION = 3201.0.0;
DYLIB_COMPATIBILITY_VERSION = 3301.0.0;
DYLIB_CURRENT_VERSION = 3301.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -9856,7 +9856,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_LINK_OBJC_RUNTIME = NO;
MARKETING_VERSION = 2.32.0;
MARKETING_VERSION = 2.33.0;
OTHER_LDFLAGS = "-liconv";
};
name = Debug;
@@ -10062,8 +10062,8 @@
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 3201.0.0;
DYLIB_CURRENT_VERSION = 3201.0.0;
DYLIB_COMPATIBILITY_VERSION = 3301.0.0;
DYLIB_CURRENT_VERSION = 3301.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
@@ -10114,8 +10114,8 @@
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 3201.0.0;
DYLIB_CURRENT_VERSION = 3201.0.0;
DYLIB_COMPATIBILITY_VERSION = 3301.0.0;
DYLIB_CURRENT_VERSION = 3301.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;

View File

@@ -1,4 +1,4 @@
Title SDL 2.32.0
Title SDL 2.33.0
Version 1
Description SDL Library for Mac OS X (http://www.libsdl.org)
DefaultLocation /Library/Frameworks

View File

@@ -60,7 +60,7 @@ import java.util.Locale;
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 2;
private static final int SDL_MINOR_VERSION = 32;
private static final int SDL_MINOR_VERSION = 33;
private static final int SDL_MICRO_VERSION = 0;
/*
// Display InputType.SOURCE/CLASS of events and devices

View File

@@ -37,6 +37,8 @@ logger = logging.getLogger(__name__)
GIT_HASH_FILENAME = ".git-hash"
REVISION_TXT = "REVISION.txt"
RE_ILLEGAL_MINGW_LIBRARIES = re.compile(r"(?:lib)?(?:gcc|(?:std)?c[+][+]|(?:win)?pthread).*", flags=re.I)
def safe_isotime_to_datetime(str_isotime: str) -> datetime.datetime:
try:
@@ -339,6 +341,12 @@ class ArchiveFileTree:
def add_file(self, file: NodeInArchive):
self._tree[file.arcpath] = file
def __iter__(self) -> typing.Iterable[NodeInArchive]:
yield from self._tree.values()
def __contains__(self, value: str) -> bool:
return value in self._tree
def get_latest_mod_time(self) -> datetime.datetime:
return max(item.time for item in self._tree.values() if item.time)
@@ -526,6 +534,16 @@ class SourceCollector:
return path_times
class AndroidApiVersion:
def __init__(self, name: str, ints: tuple[int, ...]):
self.name = name
self.ints = ints
def __repr__(self) -> str:
return f"<{self.name} ({'.'.join(str(v) for v in self.ints)})>"
ANDROID_ABI_EXTRA_LINK_OPTIONS = {}
class Releaser:
def __init__(self, release_info: dict, commit: str, revision: str, root: Path, dist_path: Path, section_printer: SectionPrinter, executer: Executer, cmake_generator: str, deps_path: Path, overwrite: bool, github: bool, fast: bool):
self.release_info = release_info
@@ -586,12 +604,22 @@ class Releaser:
def create_source_archives(self) -> None:
source_collector = SourceCollector(root=self.root, commit=self.commit, executer=self.executer, filter=self._path_filter)
print(f"Collecting sources of {self.project}...")
archive_tree = source_collector.get_archive_file_tree()
archive_tree: ArchiveFileTree = source_collector.get_archive_file_tree()
latest_mod_time = archive_tree.get_latest_mod_time()
archive_tree.add_file(NodeInArchive.from_text(arcpath=REVISION_TXT, text=f"{self.revision}\n", time=latest_mod_time))
archive_tree.add_file(NodeInArchive.from_text(arcpath=f"{GIT_HASH_FILENAME}", text=f"{self.commit}\n", time=latest_mod_time))
archive_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["source"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=latest_mod_time)
if "Makefile.am" in archive_tree:
patched_time = latest_mod_time + datetime.timedelta(minutes=1)
print(f"Makefile.am detected -> touching aclocal.m4, */Makefile.in, configure")
for node_data in archive_tree:
arc_name = os.path.basename(node_data.arcpath)
arc_name_we, arc_name_ext = os.path.splitext(arc_name)
if arc_name in ("aclocal.m4", "configure", "Makefile.in"):
print(f"Bumping time of {node_data.arcpath}")
node_data.time = patched_time
archive_base = f"{self.project}-{self.version}"
zip_path = self.dist_path / f"{archive_base}.zip"
tgz_path = self.dist_path / f"{archive_base}.tar.gz"
@@ -668,6 +696,15 @@ class Releaser:
def git_hash_data(self) -> bytes:
return f"{self.commit}\n".encode()
def verify_mingw_library(self, triplet: str, path: Path):
objdump_output = self.executer.check_output([f"{triplet}-objdump", "-p", str(path)])
libraries = re.findall(r"DLL Name: ([^\n]+)", objdump_output)
logger.info("%s (%s) libraries: %r", path, triplet, libraries)
illegal_libraries = list(filter(RE_ILLEGAL_MINGW_LIBRARIES.match, libraries))
logger.error("Detected 'illegal' libraries: %r", illegal_libraries)
if illegal_libraries:
raise Exception(f"{path} links to illegal libraries: {illegal_libraries}")
def create_mingw_archives(self) -> None:
build_type = "Release"
build_parent_dir = self.root / "build-mingw"
@@ -764,7 +801,6 @@ class Releaser:
f"--includedir=${{prefix}}/include",
f"--libdir=${{prefix}}/lib",
f"--bindir=${{prefix}}/bin",
f"--exec-prefix=${{prefix}}/bin",
f"--host={triplet}",
f"--build=x86_64-none-linux-gnu",
"CFLAGS=-O2",
@@ -772,9 +808,10 @@ class Releaser:
"LDFLAGS=-Wl,-s",
] + extra_args, cwd=build_path, env=new_env)
with self.section_printer.group(f"Build MinGW {triplet} (autotools)"):
self.executer.run(["make", "V=1", f"-j{self.cpu_count}"], cwd=build_path, env=new_env)
self.executer.run(["make", f"-j{self.cpu_count}"], cwd=build_path, env=new_env)
with self.section_printer.group(f"Install MinGW {triplet} (autotools)"):
self.executer.run(["make", "install"], cwd=build_path, env=new_env)
self.verify_mingw_library(triplet=ARCH_TO_TRIPLET[arch], path=install_path / "bin" / f"{self.project}.dll")
archive_file_tree.add_directory_tree(arc_dir=arc_join(arc_root, triplet), path=install_path, time=self.arc_time)
print("Recording arch-dependent extra files for MinGW development archive ...")
@@ -830,6 +867,7 @@ class Releaser:
self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type], cwd=build_path, env=new_env)
with self.section_printer.group(f"Install MinGW {triplet} (CMake)"):
self.executer.run(["cmake", "--install", str(build_path)], cwd=build_path, env=new_env)
self.verify_mingw_library(triplet=ARCH_TO_TRIPLET[arch], path=install_path / "bin" / f"{self.project}.dll")
archive_file_tree.add_directory_tree(arc_dir=arc_join(arc_root, triplet), path=install_path, time=self.arc_time)
print("Recording arch-dependent extra files for MinGW development archive ...")
@@ -857,22 +895,25 @@ class Releaser:
self.artifacts["mingw-devel-tar-gz"] = tgz_path
self.artifacts["mingw-devel-tar-xz"] = txz_path
def _detect_android_api(self, android_home: str) -> typing.Optional[int]:
def _detect_android_api(self, android_home: str) -> typing.Optional[AndroidApiVersion]:
platform_dirs = list(Path(p) for p in glob.glob(f"{android_home}/platforms/android-*"))
re_platform = re.compile("android-([0-9]+)")
platform_versions = []
re_platform = re.compile("^android-([0-9]+)(?:-ext([0-9]+))?$")
platform_versions: list[AndroidApiVersion] = []
for platform_dir in platform_dirs:
logger.debug("Found Android Platform SDK: %s", platform_dir)
if not (platform_dir / "android.jar").is_file():
logger.debug("Skipping SDK, missing android.jar")
continue
if m:= re_platform.match(platform_dir.name):
platform_versions.append(int(m.group(1)))
platform_versions.sort()
platform_versions.append(AndroidApiVersion(name=platform_dir.name, ints=(int(m.group(1)), int(m.group(2) or 0))))
platform_versions.sort(key=lambda v: v.ints)
logger.info("Available platform versions: %s", platform_versions)
platform_versions = list(filter(lambda v: v >= self._android_api_minimum, platform_versions))
logger.info("Valid platform versions (>=%d): %s", self._android_api_minimum, platform_versions)
platform_versions = list(filter(lambda v: v.ints >= self._android_api_minimum.ints, platform_versions))
logger.info("Valid platform versions (>=%s): %s", self._android_api_minimum.ints, platform_versions)
if not platform_versions:
return None
android_api = platform_versions[0]
logger.info("Selected API version %d", android_api)
logger.info("Selected API version %s", android_api)
return android_api
def _get_prefab_json_text(self) -> str:
@@ -896,8 +937,19 @@ class Releaser:
return json.dumps(module_json_dict, indent=4)
@property
def _android_api_minimum(self):
return self.release_info["android"]["api-minimum"]
def _android_api_minimum(self) -> AndroidApiVersion:
value = self.release_info["android"]["api-minimum"]
if isinstance(value, int):
ints = (value, )
elif isinstance(value, str):
ints = tuple(split("."))
else:
raise ValueError("Invalid android.api-minimum: must be X or X.Y")
match len(ints):
case 1: name = f"android-{ints[0]}"
case 2: name = f"android-{ints[0]}-ext-{ints[1]}"
case _: raise ValueError("Invalid android.api-minimum: must be X or X.Y")
return AndroidApiVersion(name=name, ints=ints)
@property
def _android_api_target(self):
@@ -910,7 +962,7 @@ class Releaser:
def _get_prefab_abi_json_text(self, abi: str, cpp: bool, shared: bool) -> str:
abi_json_dict = {
"abi": abi,
"api": self._android_api_minimum,
"api": self._android_api_minimum.ints[0],
"ndk": self._android_ndk_minimum,
"stl": "c++_shared" if cpp else "none",
"static": not shared,
@@ -923,7 +975,7 @@ class Releaser:
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.libsdl.android.{self.project}" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="{self._android_api_minimum}"
<uses-sdk android:minSdkVersion="{self._android_api_minimum.ints[0]}"
android:targetSdkVersion="{self._android_api_target}" />
</manifest>
""")
@@ -933,7 +985,8 @@ class Releaser:
if not cmake_toolchain_file.exists():
logger.error("CMake toolchain file does not exist (%s)", cmake_toolchain_file)
raise SystemExit(1)
aar_path = self.dist_path / f"{self.project}-{self.version}.aar"
aar_path = self.root / "build-android" / f"{self.project}-{self.version}.aar"
android_dist_path = self.dist_path / f"{self.project}-devel-{self.version}-android.zip"
android_abis = self.release_info["android"]["abis"]
java_jars_added = False
module_data_added = False
@@ -941,16 +994,27 @@ class Releaser:
shutil.rmtree(android_deps_path, ignore_errors=True)
for dep, depinfo in self.release_info["android"].get("dependencies", {}).items():
android_aar = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0]
with self.section_printer.group(f"Extracting Android dependency {dep} ({android_aar.name})"):
self.executer.run([sys.executable, str(android_aar), "-o", str(android_deps_path)])
dep_devel_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0]
dep_extract_path = self.deps_path / f"extract/android/{dep}"
shutil.rmtree(dep_extract_path, ignore_errors=True)
dep_extract_path.mkdir(parents=True, exist_ok=True)
with self.section_printer.group(f"Extracting Android dependency {dep} ({dep_devel_zip})"):
with zipfile.ZipFile(dep_devel_zip, "r") as zf:
zf.extractall(dep_extract_path)
dep_devel_aar = dep_extract_path / glob.glob("*.aar", root_dir=dep_extract_path)[0]
self.executer.run([sys.executable, str(dep_devel_aar), "-o", str(android_deps_path)])
for module_name, module_info in self.release_info["android"]["modules"].items():
assert "type" in module_info and module_info["type"] in ("interface", "library"), f"module {module_name} must have a valid type"
archive_file_tree = ArchiveFileTree()
aar_file_tree = ArchiveFileTree()
android_devel_file_tree = ArchiveFileTree()
for android_abi in android_abis:
extra_link_options = ANDROID_ABI_EXTRA_LINK_OPTIONS.get(android_abi, "")
with self.section_printer.group(f"Building for Android {android_api} {android_abi}"):
build_dir = self.root / "build-android" / f"{android_abi}-build"
install_dir = self.root / "install-android" / f"{android_abi}-install"
@@ -961,8 +1025,11 @@ class Releaser:
"cmake",
"-S", str(self.root),
"-B", str(build_dir),
f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
# 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"-DCMAKE_EXE_LINKER_FLAGS={extra_link_options}",
f"-DCMAKE_SHARED_LINKER_FLAGS={extra_link_options}",
f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}",
f"-DCMAKE_PREFIX_PATH={str(android_deps_path)}",
f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH",
@@ -999,20 +1066,20 @@ class Releaser:
assert library.suffix in (".so", ".a")
assert library.is_file(), f"CMake should have built library '{library}' for module {module_name}"
arcdir_prefab_libs = f"{arcdir_prefab_module}/libs/android.{android_abi}"
archive_file_tree.add_file(NodeInArchive.from_fs(arcpath=f"{arcdir_prefab_libs}/{library.name}", path=library, time=self.arc_time))
archive_file_tree.add_file(NodeInArchive.from_text(arcpath=f"{arcdir_prefab_libs}/abi.json", text=self._get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=library.suffix == ".so"), time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_fs(arcpath=f"{arcdir_prefab_libs}/{library.name}", path=library, time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_text(arcpath=f"{arcdir_prefab_libs}/abi.json", text=self._get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=library.suffix == ".so"), time=self.arc_time))
if not module_data_added:
library_name = None
if module_info["type"] == "library":
library_name = Path(module_info["library"]).stem.removeprefix("lib")
export_libraries = module_info.get("export-libraries", [])
archive_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_module, "module.json"), text=self._get_prefab_module_json_text(library_name=library_name, export_libraries=export_libraries), time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_module, "module.json"), text=self._get_prefab_module_json_text(library_name=library_name, export_libraries=export_libraries), time=self.arc_time))
arcdir_prefab_include = f"prefab/modules/{module_name}/include"
if "includes" in module_info:
archive_file_tree.add_file_mapping(arc_dir=arcdir_prefab_include, file_mapping=module_info["includes"], file_mapping_root=install_dir, context=self.get_context(), time=self.arc_time)
aar_file_tree.add_file_mapping(arc_dir=arcdir_prefab_include, file_mapping=module_info["includes"], file_mapping_root=install_dir, context=self.get_context(), time=self.arc_time)
else:
archive_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_include, ".keep"), text="\n", time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_include, ".keep"), text="\n", time=self.arc_time))
module_data_added = True
if not java_jars_added:
@@ -1025,21 +1092,28 @@ class Releaser:
assert sources_jar_path.is_file(), f"CMake should have archived the java sources into a JAR ({sources_jar_path})"
assert doc_jar_path.is_file(), f"CMake should have archived javadoc into a JAR ({doc_jar_path})"
archive_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes.jar", path=classes_jar_path, time=self.arc_time))
archive_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-sources.jar", path=sources_jar_path, time=self.arc_time))
archive_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-doc.jar", path=doc_jar_path, time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes.jar", path=classes_jar_path, time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-sources.jar", path=sources_jar_path, time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-doc.jar", path=doc_jar_path, time=self.arc_time))
assert ("jars" in self.release_info["android"] and java_jars_added) or "jars" not in self.release_info["android"], "Must have archived java JAR archives"
archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["android"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=self.arc_time)
aar_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["android"]["aar-files"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time)
archive_file_tree.add_file(NodeInArchive.from_text(arcpath="prefab/prefab.json", text=self._get_prefab_json_text(), time=self.arc_time))
archive_file_tree.add_file(NodeInArchive.from_text(arcpath="AndroidManifest.xml", text=self._get_android_manifest_text(), time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_text(arcpath="prefab/prefab.json", text=self._get_prefab_json_text(), time=self.arc_time))
aar_file_tree.add_file(NodeInArchive.from_text(arcpath="AndroidManifest.xml", text=self._get_android_manifest_text(), time=self.arc_time))
with Archiver(zip_path=aar_path) as archiver:
archive_file_tree.add_to_archiver(archive_base="", archiver=archiver)
aar_file_tree.add_to_archiver(archive_base="", archiver=archiver)
archiver.add_git_hash(arcdir="", commit=self.commit, time=self.arc_time)
self.artifacts[f"android-aar"] = aar_path
android_devel_file_tree.add_file(NodeInArchive.from_fs(arcpath=aar_path.name, path=aar_path))
android_devel_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["android"]["files"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time)
with Archiver(zip_path=android_dist_path) as archiver:
android_devel_file_tree.add_to_archiver(archive_base="", archiver=archiver)
archiver.add_git_hash(arcdir="", commit=self.commit, time=self.arc_time)
self.artifacts[f"android-aar"] = android_dist_path
def download_dependencies(self):
shutil.rmtree(self.deps_path, ignore_errors=True)
@@ -1076,7 +1150,7 @@ class Releaser:
assert len(msvc_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {msvc_matches}"
if "android" in self.release_info:
android_matches = glob.glob(self.release_info["android"]["dependencies"][dep]["artifact"], root_dir=self.deps_path)
assert len(android_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {msvc_matches}"
assert len(android_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {android_matches}"
@staticmethod
def _arch_to_vs_platform(arch: str, configuration: str="Release") -> VsArchPlatformConfig:
@@ -1202,6 +1276,10 @@ class Releaser:
platform_context = self.get_context(extra_context=arch_platform.extra_context())
build_type = "Release"
extra_context = {
"ARCH": arch_platform.arch,
"PLATFORM": arch_platform.platform,
}
built_paths = set(install_path / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["cmake"]["files-lib"], self.release_info["msvc"]["cmake"]["files-devel"]) for files_list in file_mapping.values() for f in files_list)
logger.info("CMake builds these files, to be included in the package: %s", built_paths)
@@ -1252,7 +1330,7 @@ class Releaser:
logger.info("Collecting files...")
archive_file_tree = ArchiveFileTree()
archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["cmake"]["files-lib"], file_mapping_root=install_path, context=platform_context, time=self.arc_time)
archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["files-lib"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time)
archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["files-lib"], file_mapping_root=self.root, context=self.get_context(extra_context=extra_context), time=self.arc_time)
logger.info("Creating %s", zip_path)
with Archiver(zip_path=zip_path) as archiver:
@@ -1316,7 +1394,7 @@ def main(argv=None) -> int:
parser.add_argument("--actions", choices=["download", "source", "android", "mingw", "msvc", "dmg"], required=True, nargs="+", dest="actions", help="What to do?")
parser.set_defaults(loglevel=logging.INFO)
parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year")
parser.add_argument('--android-api', type=int, dest="android_api", help="Android API version")
parser.add_argument('--android-api', dest="android_api", help="Android API version")
parser.add_argument('--android-home', dest="android_home", default=os.environ.get("ANDROID_HOME"), help="Android Home folder")
parser.add_argument('--android-ndk-home', dest="android_ndk_home", default=os.environ.get("ANDROID_NDK_HOME"), help="Android NDK Home folder")
parser.add_argument('--cmake-generator', dest="cmake_generator", default="Ninja", help="CMake Generator")
@@ -1443,14 +1521,27 @@ def main(argv=None) -> int:
if args.android_api is None:
with section_printer.group("Detect Android APIS"):
args.android_api = releaser._detect_android_api(android_home=args.android_home)
if args.android_api is None or not (Path(args.android_home) / f"platforms/android-{args.android_api}").is_dir():
else:
try:
android_api_ints = tuple(int(v) for v in args.android_api.split("."))
match len(android_api_ints):
case 1: android_api_name = f"android-{android_api_ints[0]}"
case 2: android_api_name = f"android-{android_api_ints[0]}-ext-{android_api_ints[1]}"
case _: raise ValueError
except ValueError:
logger.error("Invalid --android-api, must be a 'X' or 'X.Y' version")
args.android_api = AndroidApiVersion(ints=android_api_ints, name=android_api_name)
if args.android_api is None:
parser.error("Invalid --android-api, and/or could not be detected")
android_api_path = Path(args.android_home) / f"platforms/{args.android_api.name}"
if not android_api_path.is_dir():
logger.warning(f"Android API directory does not exist ({android_api_path})")
with section_printer.group("Android arguments"):
print(f"android_home = {args.android_home}")
print(f"android_ndk_home = {args.android_ndk_home}")
print(f"android_api = {args.android_api}")
releaser.create_android_archives(
android_api=args.android_api,
android_api=args.android_api.ints[0],
android_home=args.android_home,
android_ndk_home=args.android_ndk_home,
)

View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2024 Free Software Foundation, Inc.
# Copyright 1992-2025 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
timestamp='2024-07-27'
timestamp='2025-07-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2024 Free Software Foundation, Inc.
Copyright 1992-2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -1597,8 +1597,11 @@ EOF
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
*:Ironclad:*:*)
GUESS=$UNAME_MACHINE-unknown-ironclad
x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*)
GUESS=$UNAME_MACHINE-pc-ironclad-mlibc
;;
*:[Ii]ronclad:*:*)
GUESS=$UNAME_MACHINE-unknown-ironclad-mlibc
;;
esac
@@ -1808,8 +1811,8 @@ fi
exit 1
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-format: "%Y-%02m-%02d"
# time-stamp-end: "'"
# End:

View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2024 Free Software Foundation, Inc.
# Copyright 1992-2025 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
timestamp='2024-05-27'
timestamp='2025-07-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2024 Free Software Foundation, Inc.
Copyright 1992-2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -145,6 +145,7 @@ case $1 in
| kfreebsd*-gnu* \
| knetbsd*-gnu* \
| kopensolaris*-gnu* \
| ironclad-* \
| linux-* \
| managarm-* \
| netbsd*-eabi* \
@@ -242,7 +243,6 @@ case $1 in
| rombug \
| semi \
| sequent* \
| siemens \
| sgi* \
| siemens \
| sim \
@@ -261,7 +261,7 @@ case $1 in
basic_machine=$field1-$field2
basic_os=
;;
zephyr*)
tock* | zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
@@ -1194,7 +1194,7 @@ case $cpu-$vendor in
xscale-* | xscalee[bl]-*)
cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
arm64-* | aarch64le-*)
arm64-* | aarch64le-* | arm64_32-*)
cpu=aarch64
;;
@@ -1321,6 +1321,7 @@ case $cpu-$vendor in
| i960 \
| ia16 \
| ia64 \
| intelgt \
| ip2k \
| iq2000 \
| javascript \
@@ -1522,6 +1523,10 @@ EOF
kernel=nto
os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
;;
ironclad*)
kernel=ironclad
os=`echo "$basic_os" | sed -e 's|ironclad|mlibc|'`
;;
linux*)
kernel=linux
os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
@@ -1976,6 +1981,7 @@ case $os in
| atheos* \
| auroraux* \
| aux* \
| banan_os* \
| beos* \
| bitrig* \
| bme* \
@@ -2022,7 +2028,6 @@ case $os in
| ios* \
| iris* \
| irix* \
| ironclad* \
| isc* \
| its* \
| l4re* \
@@ -2118,6 +2123,7 @@ case $os in
| sysv* \
| tenex* \
| tirtos* \
| tock* \
| toppers* \
| tops10* \
| tops20* \
@@ -2214,6 +2220,8 @@ case $kernel-$os-$obj in
;;
uclinux-uclibc*- | uclinux-gnu*- )
;;
ironclad-mlibc*-)
;;
managarm-mlibc*- | managarm-kernel*- )
;;
windows*-msvc*-)
@@ -2249,6 +2257,8 @@ case $kernel-$os-$obj in
;;
*-eabi*- | *-gnueabi*-)
;;
ios*-simulator- | tvos*-simulator- | watchos*-simulator- )
;;
none--*)
# None (no kernel, i.e. freestanding / bare metal),
# can be paired with an machine code file format
@@ -2347,8 +2357,8 @@ echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-format: "%Y-%02m-%02d"
# time-stamp-end: "'"
# End:

View File

@@ -966,7 +966,7 @@ macro(CheckPTHREAD)
if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
set(PTHREAD_LDFLAGS "-mt -lpthread")
else()
set(PTHREAD_LDFLAGS "-pthread -lposix4")
set(PTHREAD_LDFLAGS "-pthread")
endif()
elseif(SYSV5)
set(PTHREAD_CFLAGS "-D_REENTRANT -Kthread")

29
configure vendored
View File

@@ -3515,7 +3515,7 @@ orig_CFLAGS="$CFLAGS"
# See docs/release_checklist.md
SDL_MAJOR_VERSION=2
SDL_MINOR_VERSION=32
SDL_MINOR_VERSION=33
SDL_MICRO_VERSION=0
SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
@@ -19755,6 +19755,12 @@ if test "x$ac_cv_func_sigaction" = xyes
then :
printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "sigtimedwait" "ac_cv_func_sigtimedwait"
if test "x$ac_cv_func_sigtimedwait" = xyes
then :
printf "%s\n" "#define HAVE_SIGTIMEDWAIT 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "setjmp" "ac_cv_func_setjmp"
if test "x$ac_cv_func_setjmp" = xyes
@@ -22422,7 +22428,6 @@ printf %s "checking for NAS audio support... " >&6; }
have_nas=yes
NAS_CFLAGS="-I/usr/X11R6/include/"
NAS_LIBS="-L/usr/X11R6/lib -laudio -lXt"
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_nas" >&5
@@ -28394,7 +28399,8 @@ fi
if test x$hidapi_support = xyes; then
if test x$have_libusb_h = xyes; then
printf "%s\n" "#define HAVE_LIBUSB 1" >>confdefs.h
printf "%s\n" "#define HAVE_LIBUSB 1" >>confdefs.h
EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBUSB_CFLAGS"
if test x$require_hidapi_libusb = xyes; then
@@ -28741,12 +28747,23 @@ printf "%s\n" "#define SDL_VIDEO_DRIVER_ANDROID 1" >>confdefs.h
if test x$enable_audio = xyes; then
case $ARCH in
sysv5|solaris|hpux)
# Newer Solaris-based systems, like OpenIndiana, don't have this interface anymore. Check for the header first.
ac_fn_c_check_header_compile "$LINENO" "sys/audioio.h" "ac_cv_header_sys_audioio_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_audioio_h" = xyes
then :
have_sys_audioio_h=yes
else $as_nop
have_sys_audioio_h=no
fi
if test x$have_sys_audioio_h = xyes; then
printf "%s\n" "#define SDL_AUDIO_DRIVER_SUNAUDIO 1" >>confdefs.h
SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
SUMMARY_audio="${SUMMARY_audio} sun"
have_audio=yes
SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
SUMMARY_audio="${SUMMARY_audio} sun"
have_audio=yes
fi
;;
netbsd) # Don't use this on OpenBSD, it's busted.

View File

@@ -12,7 +12,7 @@ orig_CFLAGS="$CFLAGS"
dnl Set various version strings - taken gratefully from the GTk sources
# See docs/release_checklist.md
SDL_MAJOR_VERSION=2
SDL_MINOR_VERSION=32
SDL_MINOR_VERSION=33
SDL_MICRO_VERSION=0
SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
@@ -359,7 +359,7 @@ dnl Checks for library functions.
AC_DEFINE(HAVE_MPROTECT, 1, [ ])
],[]),
)
AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv bsearch qsort abs bcopy memset memcmp memcpy memmove wcslen wcslcpy wcslcat _wcsdup wcsdup wcsstr wcscmp wcsncmp wcscasecmp _wcsicmp wcsncasecmp _wcsnicmp strlen strlcpy strlcat _strrev _strupr _strlwr index rindex strchr strrchr strstr strtok_r itoa _ltoa _uitoa _ultoa strtod strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp strcasestr vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname getauxval elf_aux_info poll memfd_create posix_fallocate _Exit)
AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv bsearch qsort abs bcopy memset memcmp memcpy memmove wcslen wcslcpy wcslcat _wcsdup wcsdup wcsstr wcscmp wcsncmp wcscasecmp _wcsicmp wcsncasecmp _wcsnicmp strlen strlcpy strlcat _strrev _strupr _strlwr index rindex strchr strrchr strstr strtok_r itoa _ltoa _uitoa _ultoa strtod strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp strcasestr vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction sigtimedwait setjmp nanosleep sysconf sysctlbyname getauxval elf_aux_info poll memfd_create posix_fallocate _Exit)
AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
AC_CHECK_FUNCS(acos acosf asin asinf atan atanf atan2 atan2f ceil ceilf copysign copysignf cos cosf exp expf fabs fabsf floor floorf trunc truncf fmod fmodf log logf log10 log10f lround lroundf pow powf round roundf scalbn scalbnf sin sinf sqrt sqrtf tan tanf)
@@ -1247,7 +1247,6 @@ CheckNAS()
have_nas=yes
NAS_CFLAGS="-I/usr/X11R6/include/"
NAS_LIBS="-L/usr/X11R6/lib -laudio -lXt"
fi
AC_MSG_RESULT($have_nas)
@@ -3636,7 +3635,7 @@ CheckHIDAPI()
if test x$hidapi_support = xyes; then
if test x$have_libusb_h = xyes; then
AC_DEFINE(HAVE_LIBUSB)
AC_DEFINE(HAVE_LIBUSB, 1, [ ])
EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBUSB_CFLAGS"
if test x$require_hidapi_libusb = xyes; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBUSB_LIBS"
@@ -3869,10 +3868,14 @@ case "$host" in
if test x$enable_audio = xyes; then
case $ARCH in
sysv5|solaris|hpux)
AC_DEFINE(SDL_AUDIO_DRIVER_SUNAUDIO, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
SUMMARY_audio="${SUMMARY_audio} sun"
have_audio=yes
# Newer Solaris-based systems, like OpenIndiana, don't have this interface anymore. Check for the header first.
AC_CHECK_HEADER(sys/audioio.h, have_sys_audioio_h=yes, have_sys_audioio_h=no)
if test x$have_sys_audioio_h = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_SUNAUDIO, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
SUMMARY_audio="${SUMMARY_audio} sun"
have_audio=yes
fi
;;
netbsd) # Don't use this on OpenBSD, it's busted.
AC_DEFINE(SDL_AUDIO_DRIVER_NETBSD, 1, [ ])

View File

@@ -29,7 +29,7 @@ cmake --install build
## Compiling a HelloWorld
[PSP Hello World](https://psp-dev.org/doku.php?id=tutorial:hello_world)
[PSP Hello World](https://pspdev.github.io/basic_programs.html#hello-world)
## To Do
- PSP Screen Keyboard

View File

@@ -14,7 +14,6 @@ Works out of box.
Windows:
Unfortunately there is no windows support as of yet. Support for Windows 7 is planned, but we currently have no way to test. If you have a Windows 7 WM_TOUCH supported device, and are willing to help test please contact me at jim.tla+sdl_touch@gmail.com
===========================================================================
Events
===========================================================================
SDL_FINGERDOWN:
@@ -39,7 +38,6 @@ Fields:
Same as SDL_FINGERDOWN.
===========================================================================
Functions
===========================================================================
SDL provides the ability to access the underlying SDL_Finger structures.
@@ -76,7 +74,6 @@ A SDL_Finger has the following fields:
The pressure of the touch.
===========================================================================
Notes
===========================================================================
For a complete example see test/testgesture.c

View File

@@ -153,7 +153,7 @@ extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
#define SDL_enabled_assert(condition) \
do { \
while ( !(condition) ) { \
static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \
static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, NULL, 0, NULL, NULL }; \
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
continue; /* go again. */ \

View File

@@ -648,7 +648,7 @@ extern DECLSPEC int SDLCALL SDL_GetDefaultAudioInfo(char **name,
* \param obtained an SDL_AudioSpec structure filled in with the actual output
* format; see SDL_OpenAudio() for more information.
* \param allowed_changes 0, or one or more flags OR'd together.
* \returns a valid device ID that is > 0 on success or 0 on failure; call
* \returns a valid device ID > 0 on success or 0 on failure; call
* SDL_GetError() for more information.
*
* For compatibility with SDL 1.2, this will never return 1, since

View File

@@ -193,6 +193,7 @@
#cmakedefine HAVE_MEMFD_CREATE 1
#cmakedefine HAVE_POSIX_FALLOCATE 1
#cmakedefine HAVE_SIGACTION 1
#cmakedefine HAVE_SIGTIMEDWAIT 1
#cmakedefine HAVE_SA_SIGACTION 1
#cmakedefine HAVE_SETJMP 1
#cmakedefine HAVE_NANOSLEEP 1

View File

@@ -195,6 +195,7 @@
#undef HAVE_FSEEKO
#undef HAVE_FSEEKO64
#undef HAVE_SIGACTION
#undef HAVE_SIGTIMEDWAIT
#undef HAVE_SA_SIGACTION
#undef HAVE_SETJMP
#undef HAVE_NANOSLEEP
@@ -216,6 +217,7 @@
#undef HAVE__EXIT
#else
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#define HAVE_STDINT_H 1

View File

@@ -115,7 +115,8 @@ _m_prefetch(void *__P)
#include <lasxintrin.h>
#define __LASX__
#endif
#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H) && \
(defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86))
#include <immintrin.h>
#else
#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H)

View File

@@ -1423,6 +1423,27 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE"
/**
* A variable containing a list of devices and their desired number of haptic
* (force feedback) enabled axis.
*
* The format of the string is a comma separated list of USB VID/PID pairs in
* hexadecimal form plus the number of desired axes, e.g.
*
* `0xAAAA/0xBBBB/1,0xCCCC/0xDDDD/3`
*
* This hint supports a "wildcard" device that will set the number of haptic
* axes on all initialized haptic devices which were not defined explicitly in
* this hint.
*
* `0xFFFF/0xFFFF/1`
*
* This hint should be set before a controller is opened. The number of haptic
* axes won't exceed the number of real axes found on the device.
*/
#define SDL_HINT_JOYSTICK_HAPTIC_AXES "SDL_JOYSTICK_HAPTIC_AXES"
/**
* A variable controlling whether joysticks on Linux will always treat 'hat'
* axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking

View File

@@ -49,7 +49,7 @@ typedef struct SDL_Keysym
{
SDL_Scancode scancode; /**< SDL physical key code - see SDL_Scancode for details */
SDL_Keycode sym; /**< SDL virtual key code - see SDL_Keycode for details */
Uint16 mod; /**< current key modifiers */
Uint16 mod; /**< current key modifiers - see SDL_Keymod for details */
Uint32 unused;
} SDL_Keysym;
@@ -255,7 +255,7 @@ extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name);
* On some platforms using this function activates the screen keyboard.
*
* On desktop platforms, SDL_StartTextInput() is implicitly called on SDL
* window creation which will cause events SDL_TextInputEvent and
* video subsystem initialization which will cause SDL_TextInputEvent and
* SDL_TextEditingEvent to begin emitting.
*
* \since This function is available since SDL 2.0.0.

View File

@@ -41,12 +41,18 @@
*
* A special exception is the number keys at the top of the keyboard which map
* to SDLK_0...SDLK_9 on AZERTY layouts.
*
* The actual values that might be set for this type are listed in the
* SDL_KeyCode (capital C) enumeration.
*/
typedef Sint32 SDL_Keycode;
#define SDLK_SCANCODE_MASK (1<<30)
#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK)
/**
* The possible values for keycodes.
*/
typedef enum SDL_KeyCode
{
SDLK_UNKNOWN = 0,

View File

@@ -187,8 +187,8 @@ extern DECLSPEC void SDLCALL SDL_SetMainReady(void);
* \param name the window class name, in UTF-8 encoding. If NULL, SDL
* currently uses "SDL_app" but this isn't guaranteed.
* \param style the value to use in WNDCLASSEX::style. If `name` is NULL, SDL
* currently uses `(CS_BYTEALIGNCLIENT | CS_OWNDC)` regardless of
* what is specified here.
* currently uses `(CS_BYTEALIGNCLIENT \| CS_OWNDC)` regardless
* of what is specified here.
* \param hInst the HINSTANCE to use in WNDCLASSEX::hInstance. If zero, SDL
* will use `GetModuleHandle(NULL)` instead.
* \returns 0 on success, -1 on error. SDL_GetError() may have details.

View File

@@ -30,6 +30,7 @@
* - single pixel lines
* - filled rectangles
* - texture images
* - 2D polygons
*
* The primitives may be drawn in opaque, blended, or additive modes.
*
@@ -38,7 +39,7 @@
* may also be stretched with linear interpolation.
*
* This API is designed to accelerate simple 2D operations. You may want more
* functionality such as polygons and particle effects and in that case you
* functionality such as 3D polygons and particle effects and in that case you
* should use SDL's OpenGL/Direct3D support or one of the many good 3D
* engines.
*
@@ -244,7 +245,7 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,
* \since This function is available since SDL 2.0.0.
*
* \sa SDL_CreateRenderer
* \sa SDL_CreateWindowRenderer
* \sa SDL_CreateWindowAndRenderer
* \sa SDL_DestroyRenderer
*/
extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface * surface);
@@ -787,7 +788,7 @@ extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
* Get the current render target.
*
* The default render target is the window for which the renderer was created,
* and is reported a NULL here.
* and is reported as NULL here.
*
* \param renderer the rendering context.
* \returns the current render target or NULL for the default render target.

View File

@@ -750,8 +750,12 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
#endif
#ifndef _WIN32
/* strdup is not ANSI but POSIX, and its prototype might be hidden... */
/* not for windows: might conflict with string.h where strdup may have
* dllimport attribute: https://github.com/libsdl-org/SDL/issues/12948 */
char *strdup(const char *str);
#endif
/* Starting LLVM 16, the analyser errors out if these functions do not have
their prototype defined (clang-diagnostic-implicit-function-declaration) */

View File

@@ -808,8 +808,8 @@ extern DECLSPEC int SDLCALL SDL_FillRects
*
* This assumes that the source and destination rectangles are the same size.
* If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or
* `dst`) is copied. The final blit rectangles are saved in `srcrect` and
* `dstrect` after all clipping is performed.
* `dst`) is copied. The final blit rectangle is saved in `dstrect` after all
* clipping is performed.
*
* The blit function should not be called on a locked surface.
*

View File

@@ -57,7 +57,7 @@ typedef struct SDL_version
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
*/
#define SDL_MAJOR_VERSION 2
#define SDL_MINOR_VERSION 32
#define SDL_MINOR_VERSION 33
#define SDL_PATCHLEVEL 0
/**

View File

@@ -42,15 +42,7 @@
#endif
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
/* older Emscriptens don't have this, but we need to for wasm64 compatibility. */
#ifndef MAIN_THREAD_EM_ASM_PTR
#ifdef __wasm64__
#error You need to upgrade your Emscripten compiler to support wasm64
#else
#define MAIN_THREAD_EM_ASM_PTR MAIN_THREAD_EM_ASM_INT
#endif
#endif
#include <emscripten.h>
#endif
/* The size of the stack buffer to use for rendering assert messages. */
@@ -259,7 +251,7 @@ static SDL_assert_state SDLCALL SDL_PromptAssertion(const SDL_assert_data *data,
for (;;) {
SDL_bool okay = SDL_TRUE;
/* *INDENT-OFF* */ /* clang-format off */
char *buf = (char *) MAIN_THREAD_EM_ASM_PTR({
int reply = MAIN_THREAD_EM_ASM_INT({
var str =
UTF8ToString($0) + '\n\n' +
'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
@@ -267,26 +259,31 @@ static SDL_assert_state SDLCALL SDL_PromptAssertion(const SDL_assert_data *data,
if (reply === null) {
reply = "i";
}
return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL);
return reply.length === 1 ? reply.charCodeAt(0) : -1;
}, message);
/* *INDENT-ON* */ /* clang-format on */
if (SDL_strcmp(buf, "a") == 0) {
switch (reply) {
case 'a':
state = SDL_ASSERTION_ABORT;
#if 0 /* (currently) no break functionality on Emscripten */
} else if (SDL_strcmp(buf, "b") == 0) {
case 'b':
state = SDL_ASSERTION_BREAK;
break;
#endif
} else if (SDL_strcmp(buf, "r") == 0) {
case 'r':
state = SDL_ASSERTION_RETRY;
} else if (SDL_strcmp(buf, "i") == 0) {
break;
case 'i':
state = SDL_ASSERTION_IGNORE;
} else if (SDL_strcmp(buf, "A") == 0) {
break;
case 'A':
state = SDL_ASSERTION_ALWAYS_IGNORE;
} else {
break;
default:
okay = SDL_FALSE;
break;
}
free(buf);
if (okay) {
break;

View File

@@ -62,6 +62,7 @@ static int (*ALSA_snd_pcm_hw_params_set_access)(snd_pcm_t *, snd_pcm_hw_params_t
static int (*ALSA_snd_pcm_hw_params_set_format)(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
static int (*ALSA_snd_pcm_hw_params_set_channels)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int);
static int (*ALSA_snd_pcm_hw_params_get_channels)(const snd_pcm_hw_params_t *, unsigned int *);
static int (*ALSA_snd_pcm_hw_params_get_rate)(const snd_pcm_hw_params_t *, unsigned int*, int*);
static int (*ALSA_snd_pcm_hw_params_set_rate_near)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
static int (*ALSA_snd_pcm_hw_params_set_period_size_near)(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
static int (*ALSA_snd_pcm_hw_params_get_period_size)(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
@@ -83,6 +84,12 @@ static int (*ALSA_snd_device_name_hint)(int, const char *, void ***);
static char *(*ALSA_snd_device_name_get_hint)(const void *, const char *);
static int (*ALSA_snd_device_name_free_hint)(void **);
static snd_pcm_sframes_t (*ALSA_snd_pcm_avail)(snd_pcm_t *);
static int (*ALSA_snd_pcm_info)(snd_pcm_t *, snd_pcm_info_t *);
static const char *(*ALSA_snd_pcm_info_get_name)(const snd_pcm_info_t *);
static int (*ALSA_snd_pcm_info_get_card)(const snd_pcm_info_t *);
static int (*ALSA_snd_card_get_name)(int, char **);
static int (*ALSA_snd_pcm_info_malloc)(snd_pcm_info_t **);
static void (*ALSA_snd_pcm_info_free)(snd_pcm_info_t *);
#ifdef SND_CHMAP_API_VERSION
static snd_pcm_chmap_t *(*ALSA_snd_pcm_get_chmap)(snd_pcm_t *);
static int (*ALSA_snd_pcm_chmap_print)(const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
@@ -132,6 +139,7 @@ static int load_alsa_syms(void)
SDL_ALSA_SYM(snd_pcm_hw_params_set_format);
SDL_ALSA_SYM(snd_pcm_hw_params_set_channels);
SDL_ALSA_SYM(snd_pcm_hw_params_get_channels);
SDL_ALSA_SYM(snd_pcm_hw_params_get_rate);
SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
@@ -152,6 +160,12 @@ static int load_alsa_syms(void)
SDL_ALSA_SYM(snd_device_name_get_hint);
SDL_ALSA_SYM(snd_device_name_free_hint);
SDL_ALSA_SYM(snd_pcm_avail);
SDL_ALSA_SYM(snd_pcm_info);
SDL_ALSA_SYM(snd_pcm_info_get_card);
SDL_ALSA_SYM(snd_pcm_info_get_name);
SDL_ALSA_SYM(snd_card_get_name);
SDL_ALSA_SYM(snd_pcm_info_malloc);
SDL_ALSA_SYM(snd_pcm_info_free);
#ifdef SND_CHMAP_API_VERSION
SDL_ALSA_SYM(snd_pcm_get_chmap);
SDL_ALSA_SYM(snd_pcm_chmap_print);
@@ -466,6 +480,58 @@ static void ALSA_CloseDevice(_THIS)
SDL_free(this->hidden);
}
static int ALSA_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
{
const char *device = "default";
snd_pcm_t *pcm_handle;
snd_pcm_info_t *pcm_info;
snd_pcm_stream_t stream;
int card_index;
const char *dev_name;
char *card_name = NULL;
char final_name[256];
SDL_zero(final_name);
stream = iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
if (ALSA_snd_pcm_open(&pcm_handle, device, stream, SND_PCM_NONBLOCK) < 0) {
return SDL_SetError("ALSA: Couldn't open default device");
}
if (ALSA_snd_pcm_info_malloc(&pcm_info) < 0) {
ALSA_snd_pcm_close(pcm_handle);
return SDL_SetError("ALSA: Couldn't allocate pcm_info");
}
if (ALSA_snd_pcm_info(pcm_handle, pcm_info) < 0) {
ALSA_snd_pcm_info_free(pcm_info);
ALSA_snd_pcm_close(pcm_handle);
return SDL_SetError("ALSA: Couldn't get PCM info");
}
card_index = ALSA_snd_pcm_info_get_card(pcm_info);
dev_name = ALSA_snd_pcm_info_get_name(pcm_info);
if (card_index >= 0 && ALSA_snd_card_get_name(card_index, &card_name) >= 0) {
SDL_snprintf(final_name, sizeof(final_name), "%s, %s", card_name, dev_name);
*name = SDL_strdup(final_name);
} else {
*name = SDL_strdup(dev_name ? dev_name : "Unknown ALSA Device");
}
if (spec) {
SDL_zero(*spec);
spec->freq = 48000;
spec->format = AUDIO_S16SYS;
spec->channels = 2;
spec->samples = 512;
}
ALSA_snd_pcm_info_free(pcm_info);
ALSA_snd_pcm_close(pcm_handle);
return 0;
}
static int ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
{
int status;
@@ -716,6 +782,16 @@ static void add_device(const int iscapture, const char *name, void *hint, ALSA_D
char *desc;
char *handle = NULL;
char *ptr;
snd_pcm_t *pcm_handle;
snd_pcm_stream_t stream;
snd_pcm_hw_params_t *hwparams;
unsigned int freq = 0;
int dir;
unsigned int channels = 0;
snd_pcm_uframes_t samples = 0;
SDL_AudioSpec spec;
if (!dev) {
return;
@@ -755,12 +831,36 @@ static void add_device(const int iscapture, const char *name, void *hint, ALSA_D
SDL_free(dev);
return;
}
stream = iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
if (ALSA_snd_pcm_open(&pcm_handle, handle, stream, SND_PCM_NONBLOCK) < 0) {
SDL_free(dev);
return;
}
/* Note that spec is NULL, because we are required to open the device before
* acquiring the mix format, making this information inaccessible at
* enumeration time
*/
SDL_AddAudioDevice(iscapture, desc, NULL, handle);
snd_pcm_hw_params_alloca(&hwparams);
ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
ALSA_snd_pcm_hw_params_get_rate(hwparams, &freq, &dir);
ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
ALSA_snd_pcm_hw_params_get_period_size(hwparams, &samples, &dir);
ALSA_snd_pcm_close(pcm_handle);
/* Let's fill the spec */
spec.freq = freq;
spec.channels = channels;
spec.samples = samples;
spec.silence = 0;
spec.padding = 0;
/* Can't calculate size yet because this is an exploratory device opening
* so we don't know the sample format.
* Probably AUDIO_S16SYS/SND_PCM_FORMAT_S16_LE would be a good default
* if required.*/
spec.size = 0;
SDL_AddAudioDevice(iscapture, desc, &spec, handle);
if (hint) {
free(desc);
}
@@ -975,6 +1075,7 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl)
impl->Deinitialize = ALSA_Deinitialize;
impl->CaptureFromDevice = ALSA_CaptureFromDevice;
impl->FlushCapture = ALSA_FlushCapture;
impl->GetDefaultAudioInfo = ALSA_GetDefaultAudioInfo;
impl->HasCaptureSupport = SDL_TRUE;
impl->SupportsNonPow2Samples = SDL_TRUE;

View File

@@ -383,7 +383,8 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
hint = SDL_GetHint(SDL_HINT_AUDIO_CATEGORY);
if (hint) {
if (SDL_strcasecmp(hint, "AVAudioSessionCategoryAmbient") == 0) {
if (SDL_strcasecmp(hint, "AVAudioSessionCategoryAmbient") == 0 ||
SDL_strcasecmp(hint, "ambient") == 0) {
category = AVAudioSessionCategoryAmbient;
} else if (SDL_strcasecmp(hint, "AVAudioSessionCategorySoloAmbient") == 0) {
category = AVAudioSessionCategorySoloAmbient;

View File

@@ -310,7 +310,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; }
audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
dynCall('vi', $2, [$3]);
dynCall('vp', $2, [$3]);
};
SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
@@ -326,7 +326,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
var silence_callback = function() {
SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
dynCall('vi', $2, [$3]);
dynCall('vp', $2, [$3]);
};
SDL2.capture.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
@@ -351,7 +351,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
SDL2.audio.silenceBuffer = undefined;
}
SDL2.audio.currentOutputBuffer = e['outputBuffer'];
dynCall('vi', $2, [$3]);
dynCall('vp', $2, [$3]);
};
SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
@@ -369,7 +369,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
// the buffer that gets filled here just gets ignored, so the app can make progress
// and/or avoid flooding audio queues until we can actually play audio.
SDL2.audio.currentOutputBuffer = SDL2.audio.silenceBuffer;
dynCall('vi', $2, [$3]);
dynCall('vp', $2, [$3]);
SDL2.audio.currentOutputBuffer = undefined;
};

View File

@@ -413,27 +413,32 @@ static int openslES_CreatePCMPlayer(_THIS)
SLresult result;
int i;
/* If we want to add floating point audio support (requires API level 21)
it can be done as described here:
https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point
*/
/* according to https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android,
Android's OpenSL ES only supports Uint8 and _littleendian_ Sint16.
(and float32, with an extension we use, below.) */
if (SDL_GetAndroidSDKVersion() >= 21) {
SDL_AudioFormat test_format;
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
if (SDL_AUDIO_ISSIGNED(test_format)) {
switch (test_format) {
case AUDIO_U8:
case AUDIO_S16LSB:
case AUDIO_F32LSB:
break;
default:
continue;
}
break;
}
if (!test_format) {
/* Didn't find a compatible format : */
LOGI("No compatible audio format, using signed 16-bit audio");
test_format = AUDIO_S16SYS;
LOGI("No compatible audio format, using signed 16-bit LE audio");
test_format = AUDIO_S16LSB;
}
this->spec.format = test_format;
} else {
/* Just go with signed 16-bit audio as it's the most compatible */
this->spec.format = AUDIO_S16SYS;
this->spec.format = AUDIO_S16LSB;
}
/* Update the fragment size as size in bytes */

View File

@@ -574,6 +574,25 @@ static SDL_bool get_int_param(const struct spa_pod *param, Uint32 key, int *val)
return SDL_FALSE;
}
static SDL_AudioFormat SPAFormatToSDL(enum spa_audio_format spafmt)
{
switch (spafmt) {
#define CHECKFMT(spa,sdl) case SPA_AUDIO_FORMAT_##spa: return AUDIO_##sdl
CHECKFMT(U8, U8);
CHECKFMT(S8, S8);
CHECKFMT(S16_LE, S16LSB);
CHECKFMT(S16_BE, S16MSB);
CHECKFMT(S32_LE, S32LSB);
CHECKFMT(S32_BE, S32MSB);
CHECKFMT(F32_LE, F32LSB);
CHECKFMT(F32_BE, F32MSB);
#undef CHECKFMT
default: break;
}
return 0;
}
/* Interface node callbacks */
static void node_event_info(void *object, const struct pw_node_info *info)
{
@@ -590,7 +609,7 @@ static void node_event_info(void *object, const struct pw_node_info *info)
/* Need to parse the parameters to get the sample rate */
for (i = 0; i < info->n_params; ++i) {
pw_node_enum_params(node->proxy, 0, info->params[i].id, 0, 0, NULL);
pw_node_enum_params((struct pw_node*)node->proxy, 0, info->params[i].id, 0, 0, NULL);
}
hotplug_core_sync(node);
@@ -602,6 +621,15 @@ static void node_event_param(void *object, int seq, uint32_t id, uint32_t index,
struct node_object *node = object;
struct io_node *io = node->userdata;
if ((id == SPA_PARAM_Format) && (io->spec.format == 0)) {
struct spa_audio_info_raw info;
SDL_zero(info);
if (spa_format_audio_raw_parse(param, &info) == 0) {
/*SDL_Log("Sink Format: %d, Rate: %d Hz, Channels: %d", info.format, info.rate, info.channels);*/
io->spec.format = SPAFormatToSDL(info.format);
}
}
/* Get the default frequency */
if (io->spec.freq == 0) {
get_range_param(param, SPA_FORMAT_AUDIO_rate, &io->spec.freq, NULL, NULL);
@@ -719,7 +747,9 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p
/* Begin setting the node properties */
io->id = id;
io->is_capture = is_capture;
io->spec.format = AUDIO_F32; /* Pipewire uses floats internally, other formats require conversion. */
if (io->spec.format == 0) {
io->spec.format = AUDIO_S16; /* we'll go conservative here if for some reason the format isn't known. */
}
io->name = io->buf;
io->path = io->buf + desc_buffer_len;
SDL_strlcpy(io->buf, node_desc, desc_buffer_len);

View File

@@ -497,7 +497,7 @@ static void PULSEAUDIO_FlushCapture(_THIS)
{
struct SDL_PrivateAudioData *h = this->hidden;
const void *data = NULL;
size_t nbytes = 0;
size_t nbytes = 0, buflen = 0;
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
@@ -507,19 +507,19 @@ static void PULSEAUDIO_FlushCapture(_THIS)
h->capturelen = 0;
}
while (SDL_AtomicGet(&this->enabled) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) {
buflen = PULSEAUDIO_pa_stream_readable_size(h->stream);
while (SDL_AtomicGet(&this->enabled) && (buflen > 0)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
/*printf("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!\n");*/
SDL_OpenedAudioDeviceDisconnected(this);
break;
}
if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) {
/* a new fragment is available! Just dump it. */
PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
PULSEAUDIO_pa_stream_drop(h->stream); /* drop this fragment. */
}
/* a fragment of audio present before FlushCapture was call is
available! Just drop it. */
PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
PULSEAUDIO_pa_stream_drop(h->stream);
buflen -= nbytes;
}
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);

View File

@@ -24,18 +24,12 @@
/* Allow access to a raw mixing buffer */
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#ifdef __NETBSD__
#include <sys/ioctl.h>
#include <sys/audioio.h>
#endif
#ifdef __SVR4
#include <sys/audioio.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#endif
#include <unistd.h>
#include "SDL_timer.h"

View File

@@ -424,9 +424,12 @@ static int device_class(struct udev_device *dev)
}
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER");
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE) &&
val && SDL_strcmp(val, "1") == 0) {
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
if (val && SDL_strcmp(val, "1") == 0) {
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_FALSE)) {
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
} else {
devclass |= SDL_UDEV_DEVICE_ACCELEROMETER;
}
}
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE");

View File

@@ -127,7 +127,11 @@
#define CPU_CFG2_LSX (1 << 6)
#define CPU_CFG2_LASX (1 << 7)
#if defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) && !defined(__MACOSX__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
#if !defined(SDL_CPUINFO_DISABLED) && \
!((defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))) && \
!(defined(__FreeBSD__) && defined(__powerpc__)) && \
!(defined(__LINUX__) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)) && \
defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
/* This is the brute force way of detecting instruction sets...
the idea is borrowed from the libmpeg2 library - thanks!
*/
@@ -356,6 +360,8 @@ static int CPU_haveAltiVec(void)
elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures));
altivec = cpufeatures & PPC_FEATURE_HAS_ALTIVEC;
return altivec;
#elif defined(__LINUX__) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)
altivec = getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC;
#elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP)
void (*handler)(int sig);
handler = signal(SIGILL, illegal_instruction);

View File

@@ -440,19 +440,24 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
static void SDL_InitDynamicAPILocked(void)
{
SDL_DYNAPI_ENTRYFN entry = NULL; /* funcs from here by default. */
SDL_bool use_internal = SDL_TRUE;
/* this can't use SDL_getenv_REAL, because it might allocate memory before the app can set their allocator */
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
/* We've always used LoadLibraryA for this, so this has never worked with Unicode paths on Windows. Sorry. */
char envbuf[512]; /* overflows will just report as environment variable being unset, but LoadLibraryA has a MAX_PATH of 260 anyhow, apparently. */
const DWORD rc = GetEnvironmentVariableA(SDL_DYNAMIC_API_ENVVAR, envbuf, (DWORD) sizeof (envbuf));
char *libname = ((rc != 0) && (rc < sizeof (envbuf))) ? envbuf : NULL;
#elif defined(__OS2__)
char * libname;
if (DosScanEnv(SDL_DYNAMIC_API_ENVVAR, &libname) != NO_ERROR) {
libname = NULL;
}
#else
char *libname = getenv(SDL_DYNAMIC_API_ENVVAR);
#endif
SDL_DYNAPI_ENTRYFN entry = NULL; /* funcs from here by default. */
SDL_bool use_internal = SDL_TRUE;
if (libname) {
while (*libname && !entry) {
char *ptr = libname;

View File

@@ -738,21 +738,17 @@ static void SDL_CutEvent(SDL_EventEntry *entry)
static int SDL_SendWakeupEvent(void)
{
SDL_Window *wakeup_window;
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL || !_this->SendWakeupEvent) {
return 0;
}
SDL_LockMutex(_this->wakeup_lock);
{
if (_this->wakeup_window) {
_this->SendWakeupEvent(_this, _this->wakeup_window);
/* No more wakeup events needed until we enter a new wait */
_this->wakeup_window = NULL;
}
/* We only want to do this once while waiting for an event, so set it to NULL atomically here */
wakeup_window = (SDL_Window *)SDL_AtomicSetPtr(&_this->wakeup_window, NULL);
if (wakeup_window) {
_this->SendWakeupEvent(_this, wakeup_window);
}
SDL_UnlockMutex(_this->wakeup_lock);
return 0;
}
@@ -1009,18 +1005,7 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
int status;
SDL_PumpEventsInternal(SDL_TRUE);
SDL_LockMutex(_this->wakeup_lock);
{
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
/* If status == 0 we are going to block so wakeup will be needed. */
if (status == 0) {
_this->wakeup_window = wakeup_window;
} else {
_this->wakeup_window = NULL;
}
}
SDL_UnlockMutex(_this->wakeup_lock);
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
if (status < 0) {
/* Got an error: return */
break;
@@ -1033,8 +1018,6 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
if (timeout > 0) {
Uint32 elapsed = SDL_GetTicks() - start;
if (elapsed >= (Uint32)timeout) {
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
return 0;
}
loop_timeout = (int)((Uint32)timeout - elapsed);
@@ -1049,9 +1032,9 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
}
}
SDL_AtomicSetPtr(&_this->wakeup_window, wakeup_window);
status = _this->WaitEventTimeout(_this, loop_timeout);
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
SDL_AtomicSetPtr(&_this->wakeup_window, NULL);
if (status == 0 && poll_interval != SDL_MAX_SINT16 && loop_timeout == poll_interval) {
/* We may have woken up to poll. Try again */
continue;
@@ -1318,7 +1301,7 @@ Uint8 SDL_EventState(Uint32 type, int state)
Uint8 lo = (type & 0xff);
if (SDL_disabled_events[hi] &&
(SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) {
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
current_state = SDL_DISABLE;
} else {
current_state = SDL_ENABLE;
@@ -1332,11 +1315,11 @@ Uint8 SDL_EventState(Uint32 type, int state)
}
/* Out of memory, nothing we can do... */
if (SDL_disabled_events[hi]) {
SDL_disabled_events[hi]->bits[lo / 32] |= (1 << (lo & 31));
SDL_disabled_events[hi]->bits[lo / 32] |= (1U << (lo & 31));
SDL_FlushEvent(type);
}
} else { // state == SDL_ENABLE
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1 << (lo & 31));
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1U << (lo & 31));
}
#ifndef SDL_JOYSTICK_DISABLED

View File

@@ -23,6 +23,85 @@
#include "SDL_syshaptic.h"
#include "SDL_haptic_c.h"
#include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */
#include "SDL_hints.h"
#include "../SDL_hints_c.h"
typedef struct SDL_Haptic_VIDPID_Naxes {
Uint16 vid;
Uint16 pid;
Uint16 naxes;
} SDL_Haptic_VIDPID_Naxes;
static void SDL_HapticLoadAxesList(SDL_Haptic_VIDPID_Naxes **entries, int *num_entries)
{
SDL_Haptic_VIDPID_Naxes entry;
const char *spot;
int length = 0;
spot = SDL_GetHint(SDL_HINT_JOYSTICK_HAPTIC_AXES);
if (!spot)
return;
while (SDL_sscanf(spot, "0x%hx/0x%hx/%hu%n", &entry.vid, &entry.pid, &entry.naxes, &length) == 3) {
SDL_assert(length > 0);
spot += length;
length = 0;
if ((*num_entries % 8) == 0) {
int new_max = *num_entries + 8;
SDL_Haptic_VIDPID_Naxes *new_entries =
(SDL_Haptic_VIDPID_Naxes *)SDL_realloc(*entries, new_max * sizeof(**entries));
// Out of memory, go with what we have already
if (!new_entries)
break;
*entries = new_entries;
}
(*entries)[(*num_entries)++] = entry;
if (spot[0] == ',')
spot++;
}
}
// /* Return -1 if not found */
static int SDL_HapticNaxesListIndex(struct SDL_Haptic_VIDPID_Naxes *entries, int num_entries, Uint16 vid, Uint16 pid)
{
int i;
if (!entries)
return -1;
for (i = 0; i < num_entries; ++i) {
if (entries[i].vid == vid && entries[i].pid == pid)
return i;
}
return -1;
}
// Check if device needs a custom number of naxes
static int SDL_HapticGetNaxes(Uint16 vid, Uint16 pid)
{
int num_entries = 0, index = 0, naxes = -1;
SDL_Haptic_VIDPID_Naxes *naxes_list = NULL;
SDL_HapticLoadAxesList(&naxes_list, &num_entries);
if (!num_entries || !naxes_list)
return -1;
// Perform "wildcard" pass
index = SDL_HapticNaxesListIndex(naxes_list, num_entries, 0xffff, 0xffff);
if (index >= 0)
naxes = naxes_list[index].naxes;
index = SDL_HapticNaxesListIndex(naxes_list, num_entries, vid, pid);
if (index >= 0)
naxes = naxes_list[index].naxes;
SDL_free(naxes_list);
return naxes;
}
/* Global for SDL_windowshaptic.c */
#if defined(SDL_HAPTIC_DINPUT) || defined(SDL_HAPTIC_XINPUT)
@@ -258,6 +337,8 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
{
SDL_Haptic *haptic;
SDL_Haptic *hapticlist;
int naxes, general_axes;
Uint16 vid, pid;
/* Make sure there is room. */
if (SDL_NumHaptics() <= 0) {
@@ -314,6 +395,18 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
}
SDL_UnlockJoysticks();
vid = SDL_JoystickGetVendor(joystick);
pid = SDL_JoystickGetProduct(joystick);
general_axes = SDL_JoystickNumAxes(joystick);
naxes = SDL_HapticGetNaxes(vid, pid);
if (naxes > 0)
haptic->naxes = naxes;
// Limit to the actual number of axes found on the device
if (general_axes >= 0 && naxes > general_axes)
haptic->naxes = general_axes;
/* Add haptic to list */
++haptic->ref_count;
/* Link the haptic in the list */

View File

@@ -630,11 +630,9 @@ static const SDL_UDEV_Symbols *udev_ctx = NULL;
#ifdef SDL_JOYSTICK_HIDAPI_STEAMXBOX
#define HAVE_DRIVER_BACKEND 1
#else
#define HAVE_DRIVER_BACKEND 0
#endif
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
/* DRIVER HIDAPI Implementation */
@@ -905,7 +903,7 @@ IsInWhitelist(Uint16 vendor, Uint16 product)
return SDL_FALSE;
}
#if defined(HAVE_PLATFORM_BACKEND) || HAVE_DRIVER_BACKEND
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND)
#define use_libusb_whitelist_default SDL_TRUE
#else
#define use_libusb_whitelist_default SDL_FALSE
@@ -951,7 +949,7 @@ static const struct hidapi_backend PLATFORM_Backend = {
};
#endif /* HAVE_PLATFORM_BACKEND */
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
static const struct hidapi_backend DRIVER_Backend = {
(void *)DRIVER_hid_write,
(void *)DRIVER_hid_read_timeout,
@@ -993,7 +991,7 @@ struct SDL_hid_device_
};
static char device_magic;
#if defined(HAVE_PLATFORM_BACKEND) || HAVE_DRIVER_BACKEND || defined(HAVE_LIBUSB)
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB)
static SDL_hid_device *CreateHIDDeviceWrapper(void *device, const struct hidapi_backend *backend)
{
@@ -1019,7 +1017,7 @@ static void DeleteHIDDeviceWrapper(SDL_hid_device *device)
}
#ifndef SDL_HIDAPI_DISABLED
#if defined(HAVE_PLATFORM_BACKEND) || HAVE_DRIVER_BACKEND || defined(HAVE_LIBUSB)
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB)
#define COPY_IF_EXISTS(var) \
if (pSrc->var != NULL) { \
@@ -1249,12 +1247,12 @@ Uint32 SDL_hid_device_change_count(void)
struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
#if defined(HAVE_PLATFORM_BACKEND) || HAVE_DRIVER_BACKEND || defined(HAVE_LIBUSB)
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB)
#ifdef HAVE_LIBUSB
struct SDL_hid_device_info *usb_devs = NULL;
struct SDL_hid_device_info *usb_dev;
#endif
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
struct SDL_hid_device_info *driver_devs = NULL;
struct SDL_hid_device_info *driver_dev;
#endif
@@ -1309,7 +1307,7 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
}
#endif /* HAVE_LIBUSB */
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
driver_devs = DRIVER_hid_enumerate(vendor_id, product_id);
for (driver_dev = driver_devs; driver_dev; driver_dev = driver_dev->next) {
new_dev = (struct SDL_hid_device_info *)SDL_malloc(sizeof(struct SDL_hid_device_info));
@@ -1347,7 +1345,7 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
}
}
#endif
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
for (driver_dev = driver_devs; driver_dev; driver_dev = driver_dev->next) {
if (raw_dev->vendor_id == driver_dev->vendor_id &&
raw_dev->product_id == driver_dev->product_id &&
@@ -1412,7 +1410,7 @@ void SDL_hid_free_enumeration(struct SDL_hid_device_info *devs)
SDL_hid_device *SDL_hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
{
#if defined(HAVE_PLATFORM_BACKEND) || HAVE_DRIVER_BACKEND || defined(HAVE_LIBUSB)
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB)
void *pDevice = NULL;
if (SDL_hidapi_refcount == 0 && SDL_hid_init() != 0) {
@@ -1428,7 +1426,7 @@ SDL_hid_device *SDL_hid_open(unsigned short vendor_id, unsigned short product_id
}
#endif /* HAVE_PLATFORM_BACKEND */
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
pDevice = DRIVER_hid_open(vendor_id, product_id, serial_number);
if (pDevice != NULL) {
return CreateHIDDeviceWrapper(pDevice, &DRIVER_Backend);
@@ -1451,7 +1449,7 @@ SDL_hid_device *SDL_hid_open(unsigned short vendor_id, unsigned short product_id
SDL_hid_device *SDL_hid_open_path(const char *path, int bExclusive /* = false */)
{
#if defined(HAVE_PLATFORM_BACKEND) || HAVE_DRIVER_BACKEND || defined(HAVE_LIBUSB)
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB)
void *pDevice = NULL;
if (SDL_hidapi_refcount == 0 && SDL_hid_init() != 0) {
@@ -1467,7 +1465,7 @@ SDL_hid_device *SDL_hid_open_path(const char *path, int bExclusive /* = false */
}
#endif /* HAVE_PLATFORM_BACKEND */
#if HAVE_DRIVER_BACKEND
#ifdef HAVE_DRIVER_BACKEND
pDevice = DRIVER_hid_open_path(path, bExclusive);
if (pDevice != NULL) {
return CreateHIDDeviceWrapper(pDevice, &DRIVER_Backend);

View File

@@ -1135,11 +1135,14 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
void HID_API_EXPORT hid_close(hid_device *dev)
{
int disconnected;
if (!dev)
return;
/* Disconnect the report callback before close. */
if (!dev->disconnected) {
disconnected = dev->disconnected;
if (!disconnected) {
IOHIDDeviceRegisterInputReportCallback(
dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
NULL, dev);
@@ -1163,7 +1166,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
/* Close the OS handle to the device, but only if it's not
been unplugged. If it's been unplugged, then calling
IOHIDDeviceClose() will crash. */
if (!dev->disconnected) {
if (!disconnected) {
IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeNone);
}

View File

@@ -62,9 +62,7 @@
#define SWITCH_GYRO_SCALE 14.2842f
#define SWITCH_ACCEL_SCALE 4096.f
#define SWITCH_GYRO_SCALE_OFFSET 13371.0f
#define SWITCH_GYRO_SCALE_MULT 936.0f
#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f
#define SWITCH_ACCEL_SCALE_MULT 4.0f
typedef enum
@@ -817,6 +815,8 @@ static SDL_bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
SwitchSubcommandInputPacket_t *factory_reply = NULL;
SwitchSPIOpData_t readUserParams;
SwitchSPIOpData_t readFactoryParams;
const int MAX_ATTEMPTS = 3;
int attempt;
/* Read User Calibration Info */
readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset;
@@ -829,8 +829,19 @@ static SDL_bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
return SDL_FALSE;
for (attempt = 0; ; ++attempt) {
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
return SDL_FALSE;
}
if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
/* We successfully read the calibration data */
break;
}
if (attempt == MAX_ATTEMPTS) {
return SDL_FALSE;
}
}
/* Automatically select the user calibration if magic bytes are set */
@@ -912,6 +923,8 @@ static SDL_bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply)) {
Uint8 *pIMUScale;
Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ;
Sint16 sAccelSensCoeffX, sAccelSensCoeffY, sAccelSensCoeffZ;
Sint16 sGyroSensCoeffX, sGyroSensCoeffY, sGyroSensCoeffZ;
/* IMU scale gives us multipliers for converting raw values to real world values */
pIMUScale = reply->spiReadData.rgucReadData;
@@ -920,10 +933,18 @@ static SDL_bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
sAccelRawY = (pIMUScale[3] << 8) | pIMUScale[2];
sAccelRawZ = (pIMUScale[5] << 8) | pIMUScale[4];
sAccelSensCoeffX = (pIMUScale[7] << 8) | pIMUScale[6];
sAccelSensCoeffY = (pIMUScale[9] << 8) | pIMUScale[8];
sAccelSensCoeffZ = (pIMUScale[11] << 8) | pIMUScale[10];
sGyroRawX = (pIMUScale[13] << 8) | pIMUScale[12];
sGyroRawY = (pIMUScale[15] << 8) | pIMUScale[14];
sGyroRawZ = (pIMUScale[17] << 8) | pIMUScale[16];
sGyroSensCoeffX = (pIMUScale[19] << 8) | pIMUScale[18];
sGyroSensCoeffY = (pIMUScale[21] << 8) | pIMUScale[20];
sGyroSensCoeffZ = (pIMUScale[23] << 8) | pIMUScale[22];
/* Check for user calibration data. If it's present and set, it'll override the factory settings */
readParams.unAddress = k_unSPIIMUUserScaleStartOffset;
readParams.ucLength = k_unSPIIMUUserScaleLength;
@@ -940,14 +961,14 @@ static SDL_bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
}
/* Accelerometer scale */
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
/* Gyro scale */
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawX) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawY) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawZ) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * (float)M_PI / 180.0f;
} else {
/* Use default values */
@@ -969,15 +990,17 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
{
sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter;
if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
if (sRawValue >= 0) {
if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax,
SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
@@ -987,15 +1010,17 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt
sRawValue -= usJoystickCenter;
if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
if (sRawValue >= 0) {
if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax,
SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
@@ -1426,6 +1451,10 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
ctx->m_bSyncWrite = SDL_TRUE;
if (!ctx->m_bInputOnly) {
#ifdef SDL_PLATFORM_MACOS
// Wait for the OS to finish its handshake with the controller
SDL_Delay(250);
#endif
GetInitialInputMode(ctx);
ctx->m_nCurrentInputMode = ctx->m_nInitialInputMode;

View File

@@ -822,11 +822,12 @@ SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJo
++SDL_HIDAPI_numjoysticks;
SDL_PrivateJoystickAdded(joystickID);
if (pJoystickID) {
*pJoystickID = joystickID;
}
SDL_PrivateJoystickAdded(joystickID);
return SDL_TRUE;
}
@@ -890,10 +891,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
return NULL;
}
device->magic = &SDL_HIDAPI_device_magic;
device->path = SDL_strdup(info->path);
if (!device->path) {
SDL_free(device);
return NULL;
if (info->path) {
device->path = SDL_strdup(info->path);
}
device->seen = SDL_TRUE;
device->vendor_id = info->vendor_id;

View File

@@ -908,9 +908,11 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
char *product_string = NULL;
WCHAR string[128];
string[0] = 0;
if (SDL_HidD_GetManufacturerString(hFile, string, sizeof(string))) {
manufacturer_string = WIN_StringToUTF8W(string);
}
string[0] = 0;
if (SDL_HidD_GetProductString(hFile, string, sizeof(string))) {
product_string = WIN_StringToUTF8W(string);
}

View File

@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,32,0,0
PRODUCTVERSION 2,32,0,0
FILEVERSION 2,33,0,0
PRODUCTVERSION 2,33,0,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "2, 32, 0, 0\0"
VALUE "FileVersion", "2, 33, 0, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL2.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "2, 32, 0, 0\0"
VALUE "ProductVersion", "2, 33, 0, 0\0"
END
END
BLOCK "VarFileInfo"

View File

@@ -975,8 +975,8 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co
}
if (texture) {
SDL_Vertex *verts = (SDL_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
uintptr_t base = (uintptr_t)vertices + cmd->data.draw.first; // address of first vertex, or base offset when using VBOs.
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)(base + offsetof(SDL_Vertex, tex_coord)));
}
if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
@@ -1009,9 +1009,9 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co
/* all drawing commands use this */
{
SDL_VertexSolid *verts = (SDL_VertexSolid *)(((Uint8 *)vertices) + cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->position);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE /* Normalized */, stride, (const GLvoid *)&verts->color);
uintptr_t base = (uintptr_t)vertices + cmd->data.draw.first; // address of first vertex, or base offset when using VBOs.
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)(base + offsetof(SDL_VertexSolid, position)));
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE /* Normalized */, stride, (const GLvoid *)(base + offsetof(SDL_VertexSolid, color)));
}
return 0;
@@ -1200,7 +1200,8 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
data->current_vertex_buffer = 0;
}
vertices = NULL; /* attrib pointers will be offsets into the VBO. */
// attrib pointers will be offsets into the VBO.
vertices = (void *)(uintptr_t)0; // must be the exact value 0, not NULL (the representation of NULL is not guaranteed to be 0).
#endif
while (cmd) {
@@ -2220,8 +2221,8 @@ SDL_RenderDriver GLES2_RenderDriver = {
{ "opengles2",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
4,
{ SDL_PIXELFORMAT_BGRA32,
SDL_PIXELFORMAT_ABGR32,
{ SDL_PIXELFORMAT_RGBA32,
SDL_PIXELFORMAT_BGRA32,
SDL_PIXELFORMAT_BGRX32,
SDL_PIXELFORMAT_RGBX32 },
0,

View File

@@ -55,7 +55,7 @@ typedef struct
static int vsync_sema_id = 0;
/* PRIVATE METHODS */
static int vsync_handler(void)
static int vsync_handler(int reason)
{
iSignalSema(vsync_sema_id);

View File

@@ -826,6 +826,35 @@ static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
return 0;
}
static void ClampCliprectToViewport(SDL_Rect *clip, const SDL_Rect *viewport)
{
int max_x_v, max_y_v, max_x_c, max_y_c;
if (clip->x < 0) {
clip->w += clip->x;
clip->x = 0;
}
if (clip->y < 0) {
clip->h += clip->y;
clip->y = 0;
}
max_x_c = clip->x + clip->w;
max_y_c = clip->y + clip->h;
max_x_v = viewport->x + viewport->w;
max_y_v = viewport->y + viewport->h;
if (max_x_c > max_x_v) {
clip->w -= (max_x_v - max_x_c);
}
if (max_y_c > max_y_v) {
clip->h -= (max_y_v - max_y_c);
}
}
static int SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
@@ -868,9 +897,13 @@ static int SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
}
if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
const SDL_Rect *rect = &data->drawstate.cliprect;
set_clip_rectangle(data, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
if ((data->drawstate.cliprect_enabled || data->drawstate.viewport_is_set) && data->drawstate.cliprect_dirty) {
SDL_Rect rect;
SDL_copyp(&rect, &data->drawstate.cliprect);
if (data->drawstate.viewport_is_set) {
ClampCliprectToViewport(&rect, &data->drawstate.viewport);
}
set_clip_rectangle(data, rect.x, rect.y, rect.x + rect.w, rect.y + rect.h);
data->drawstate.cliprect_dirty = SDL_FALSE;
}
@@ -925,20 +958,27 @@ static int SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata;
int w, h;
StartDrawing(renderer);
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
int w, h;
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
} else {
if (SDL_QueryTexture(renderer->target, NULL, NULL, &w, &h) < 0) {
w = data->drawstate.drawablew;
h = data->drawstate.drawableh;
}
}
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}
while (cmd) {
switch (cmd->command) {
@@ -949,6 +989,16 @@ static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *c
SDL_copyp(viewport, &cmd->data.viewport.rect);
data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.viewport_is_set = viewport->x != 0 || viewport->y != 0 || viewport->w != data->drawstate.drawablew || viewport->h != data->drawstate.drawableh;
if (!data->drawstate.cliprect_enabled) {
if (data->drawstate.viewport_is_set) {
SDL_copyp(&data->drawstate.cliprect, viewport);
data->drawstate.cliprect.x = 0;
data->drawstate.cliprect.y = 0;
} else {
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
}
}
break;
}
@@ -956,9 +1006,15 @@ static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *c
case SDL_RENDERCMD_SETCLIPRECT:
{
const SDL_Rect *rect = &cmd->data.cliprect.rect;
const SDL_Rect *viewport = &data->drawstate.viewport;
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
if (!data->drawstate.cliprect_enabled && data->drawstate.viewport_is_set) {
SDL_copyp(&data->drawstate.cliprect, viewport);
data->drawstate.cliprect.x = 0;
data->drawstate.cliprect.y = 0;
}
}
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {

View File

@@ -106,6 +106,7 @@ typedef struct
{
SDL_Rect viewport;
SDL_bool viewport_dirty;
SDL_bool viewport_is_set;
SDL_Texture *texture;
SDL_Texture *target;
SDL_Color color;

View File

@@ -81,14 +81,12 @@ static size_t SDL_ScanUnsignedLongLongInternal(const char *text, int count, int
negative = *text == '-';
++text;
}
if ((radix == 0 || radix == 16) && *text == '0' && text[1] != '\0') {
if ((radix == 0 || radix == 16) && *text == '0' && (text[1] == 'x' || text[1] == 'X')) {
text += 2;
radix = 16;
} else if (radix == 0 && *text == '0' && (text[1] >= '0' && text[1] <= '9')) {
++text;
if (*text == 'x' || *text == 'X') {
radix = 16;
++text;
} else if (radix == 0) {
radix = 8;
}
radix = 8;
} else if (radix == 0) {
radix = 10;
}
@@ -1113,6 +1111,7 @@ static SDL_bool CharacterMatchesSet(char c, const char *set, size_t set_len)
/* NOLINTNEXTLINE(readability-non-const-parameter) */
int SDL_vsscanf(const char *text, const char *fmt, va_list ap)
{
const char *start = text;
int retval = 0;
if (!text || !*text) {
@@ -1383,6 +1382,36 @@ int SDL_vsscanf(const char *text, const char *fmt, va_list ap)
}
done = SDL_TRUE;
break;
case 'n':
switch (inttype) {
case DO_SHORT:
{
short *valuep = va_arg(ap, short *);
*valuep = (short)(text - start);
} break;
case DO_INT:
{
int *valuep = va_arg(ap, int *);
*valuep = (int)(text - start);
} break;
case DO_LONG:
{
long *valuep = va_arg(ap, long *);
*valuep = (long)(text - start);
} break;
case DO_LONGLONG:
{
long long *valuep = va_arg(ap, long long *);
*valuep = (long long)(text - start);
} break;
case DO_SIZE_T:
{
size_t *valuep = va_arg(ap, size_t *);
*valuep = (size_t)(text - start);
} break;
}
done = SDL_TRUE;
break;
case '[':
{
const char *set = fmt + 1;

View File

@@ -34,6 +34,8 @@
#include <pspkerneltypes.h>
#include <pspthreadman.h>
#define PSP_THREAD_NAME_MAX 32
static int ThreadEntry(SceSize args, void *argp)
{
SDL_RunThread(*(SDL_Thread **)argp);
@@ -44,6 +46,7 @@ int SDL_SYS_CreateThread(SDL_Thread *thread)
{
SceKernelThreadInfo status;
int priority = 32;
char thread_name[PSP_THREAD_NAME_MAX];
/* Set priority of new thread to the same as the current thread */
status.size = sizeof(SceKernelThreadInfo);
@@ -51,7 +54,12 @@ int SDL_SYS_CreateThread(SDL_Thread *thread)
priority = status.currentPriority;
}
thread->handle = sceKernelCreateThread(thread->name, ThreadEntry,
SDL_strlcpy(thread_name, "SDL thread", PSP_THREAD_NAME_MAX);
if (thread->name) {
SDL_strlcpy(thread_name, thread->name, PSP_THREAD_NAME_MAX);
}
thread->handle = sceKernelCreateThread(thread_name, ThreadEntry,
priority, thread->stacksize ? ((int)thread->stacksize) : 0x8000,
PSP_THREAD_ATTR_VFPU, NULL);
if (thread->handle < 0) {

View File

@@ -159,7 +159,7 @@ void SDL_SYS_SetupThread(const char *name)
inf.dwFlags = 0;
/* The debugger catches this, renames the thread, continues on. */
RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR *)&inf);
RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG_PTR), (const ULONG_PTR *)&inf);
}
}
}

View File

@@ -355,8 +355,7 @@ struct SDL_VideoDevice
SDL_bool checked_texture_framebuffer;
SDL_bool is_dummy;
SDL_bool suspend_screensaver;
SDL_Window *wakeup_window;
SDL_mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */
void *wakeup_window;
int num_displays;
SDL_VideoDisplay *displays;
SDL_Window *windows;
@@ -400,6 +399,7 @@ struct SDL_VideoDevice
int no_error;
int retained_backing;
int driver_loaded;
int HAS_GL_ARB_color_buffer_float;
char driver_path[256];
void *dll_handle;
} gl_config;

View File

@@ -70,6 +70,10 @@
#include <dlfcn.h>
#endif
#ifndef GL_RGBA_FLOAT_MODE_ARB
#define GL_RGBA_FLOAT_MODE_ARB 0x8820
#endif /* GL_RGBA_FLOAT_MODE_ARB */
/* Available video drivers */
static VideoBootStrap *bootstrap[] = {
#ifdef SDL_VIDEO_DRIVER_COCOA
@@ -3368,9 +3372,7 @@ void SDL_DestroyWindow(SDL_Window *window)
_this->current_glwin = NULL;
}
if (_this->wakeup_window == window) {
_this->wakeup_window = NULL;
}
SDL_AtomicCASPtr(&_this->wakeup_window, window, NULL);
/* Now invalidate magic */
window->magic = NULL;
@@ -4038,6 +4040,15 @@ int SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
*value = _this->gl_config.no_error;
return 0;
}
case SDL_GL_FLOATBUFFERS:
{
if (_this->gl_config.HAS_GL_ARB_color_buffer_float) {
attrib = GL_RGBA_FLOAT_MODE_ARB;
break;
} else {
return 0;
}
}
default:
return SDL_SetError("Unknown OpenGL attribute");
}

View File

@@ -287,9 +287,19 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
/* The menu bar of SDL apps which don't have the typical .app bundle
* structure fails to work the first time a window is created (until it's
* de-focused and re-focused), if this call is in Cocoa_RegisterApp instead
* of here. https://bugzilla.libsdl.org/show_bug.cgi?id=3051
* of here. https://github.com/libsdl-org/SDL/issues/1913
*/
if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, SDL_FALSE)) {
/* this apparently became unnecessary on macOS 14.0, and will addition pop up a
hidden dock if you're moving the mouse during launch, so change the default
behaviour there. https://github.com/libsdl-org/SDL/issues/10340
(13.6 still needs it, presumably 13.7 does, too.) */
SDL_bool background_app_default = SDL_FALSE;
if (@available(macOS 14.0, *)) {
background_app_default = SDL_TRUE; /* by default, don't explicitly activate the dock and then us again to force to foreground */
}
if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, background_app_default)) {
/* Get more aggressive for Catalina: activate the Dock first so we definitely reset all activation state. */
for (NSRunningApplication *i in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
[i activateWithOptions:NSApplicationActivateIgnoringOtherApps];

View File

@@ -48,9 +48,6 @@ static void Cocoa_VideoQuit(_THIS);
static void Cocoa_DeleteDevice(SDL_VideoDevice * device)
{ @autoreleasepool
{
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
CFBridgingRelease(device->driverdata);
SDL_free(device);
}}
@@ -76,7 +73,6 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
return NULL;
}
device->driverdata = (void *)CFBridgingRetain(data);
device->wakeup_lock = SDL_CreateMutex();
/* Set the function pointers */
device->VideoInit = Cocoa_VideoInit;

View File

@@ -855,6 +855,11 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
/* The OS can resize the window automatically if the display density
changes while the window is miniaturized or hidden */
if (![nswindow isVisible])
return;
/* isZoomed always returns true if the window is not resizable */
if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
zoomed = YES;

View File

@@ -79,7 +79,7 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect
if (!Module['SDL2']) Module['SDL2'] = {};
var SDL2 = Module['SDL2'];
if (SDL2.ctxCanvas !== Module['canvas']) {
SDL2.ctx = Module['createContext'](Module['canvas'], false, true);
SDL2.ctx = Browser.createContext(Module['canvas'], false, true);
SDL2.ctxCanvas = Module['canvas'];
}
if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) {

View File

@@ -40,6 +40,48 @@
*/
#define PIPE_MS_TIMEOUT 14
/* sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it.
* Based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation
*/
#ifndef HAVE_SIGTIMEDWAIT
#include <errno.h>
#include <time.h>
static int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout)
{
struct timespec elapsed = { 0 }, rem = { 0 };
sigset_t pending;
int signo;
do {
/* Check the pending signals, and call sigwait if there is at least one of interest in the set. */
sigpending(&pending);
for (signo = 1; signo < NSIG; ++signo) {
if (sigismember(set, signo) && sigismember(&pending, signo)) {
if (!sigwait(set, &signo)) {
if (info) {
SDL_memset(info, 0, sizeof *info);
info->si_signo = signo;
}
return signo;
} else {
return -1;
}
}
}
if (timeout->tv_sec || timeout->tv_nsec) {
long ns = 20000000L; // 2/100ths of a second
nanosleep(&(struct timespec){ 0, ns }, &rem);
ns -= rem.tv_nsec;
elapsed.tv_sec += (elapsed.tv_nsec + ns) / 1000000000L;
elapsed.tv_nsec = (elapsed.tv_nsec + ns) % 1000000000L;
}
} while (elapsed.tv_sec < timeout->tv_sec || (elapsed.tv_sec == timeout->tv_sec && elapsed.tv_nsec < timeout->tv_nsec));
errno = EAGAIN;
return -1;
}
#endif
static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_t *pos)
{
int ready = 0;
@@ -75,7 +117,7 @@ static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_
}
}
sigtimedwait(&sig_set, 0, &zerotime);
sigtimedwait(&sig_set, NULL, &zerotime);
#ifdef SDL_THREADS_DISABLED
sigprocmask(SIG_SETMASK, &old_sig_set, NULL);

View File

@@ -162,9 +162,6 @@ static void Wayland_DeleteDevice(SDL_VideoDevice *device)
WAYLAND_wl_display_flush(data->display);
WAYLAND_wl_display_disconnect(data->display);
}
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(data);
SDL_free(device);
SDL_WAYLAND_UnloadSymbols();
@@ -233,7 +230,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
}
device->driverdata = data;
device->wakeup_lock = SDL_CreateMutex();
/* Set the function pointers */
device->VideoInit = Wayland_VideoInit;

View File

@@ -511,6 +511,10 @@ void WIN_GL_InitExtensions(_THIS)
_this->gl_data->HAS_WGL_ARB_create_context_no_error = SDL_TRUE;
}
/* Check for WGL_ARB_pixel_format_float */
_this->gl_data->HAS_WGL_ARB_pixel_format_float =
HasExtension("WGL_ARB_pixel_format_float", extensions);
_this->gl_data->wglMakeCurrent(hdc, NULL);
_this->gl_data->wglDeleteContext(hglrc);
ReleaseDC(hwnd, hdc);
@@ -641,7 +645,7 @@ static int WIN_GL_SetupWindowInternal(_THIS, SDL_Window *window)
*iAttr++ = _this->gl_config.multisamplesamples;
}
if (_this->gl_config.floatbuffers) {
if (_this->gl_data->HAS_WGL_ARB_pixel_format_float && _this->gl_config.floatbuffers) {
*iAttr++ = WGL_PIXEL_TYPE_ARB;
*iAttr++ = WGL_TYPE_RGBA_FLOAT_ARB;
}
@@ -825,6 +829,9 @@ SDL_GLContext WIN_GL_CreateContext(_THIS, SDL_Window *window)
return NULL;
}
_this->gl_config.HAS_GL_ARB_color_buffer_float =
SDL_GL_ExtensionSupported("GL_ARB_color_buffer_float");
return context;
}

View File

@@ -64,6 +64,7 @@ struct SDL_GLDriverData
SDL_bool HAS_WGL_ARB_context_flush_control;
SDL_bool HAS_WGL_ARB_create_context_robustness;
SDL_bool HAS_WGL_ARB_create_context_no_error;
SDL_bool HAS_WGL_ARB_pixel_format_float;
/* Max version of OpenGL ES context that can be created if the
implementation supports WGL_EXT_create_context_es2_profile.

View File

@@ -93,9 +93,6 @@ static void WIN_DeleteDevice(SDL_VideoDevice *device)
SDL_UnloadObject(data->shcoreDLL);
}
#endif
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(device->driverdata);
SDL_free(device);
}
@@ -120,7 +117,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
return NULL;
}
device->driverdata = data;
device->wakeup_lock = SDL_CreateMutex();
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
data->userDLL = SDL_LoadObject("USER32.DLL");

View File

@@ -108,9 +108,6 @@ static void X11_DeleteDevice(SDL_VideoDevice *device)
X11_XCloseDisplay(data->request_display);
}
SDL_free(data->windowlist);
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(device->driverdata);
SDL_free(device);
@@ -204,8 +201,6 @@ static SDL_VideoDevice *X11_CreateDevice(void)
return NULL;
}
device->wakeup_lock = SDL_CreateMutex();
#ifdef X11_DEBUG
X11_XSynchronize(data->display, True);
#endif

View File

@@ -67,6 +67,9 @@ static SDL_bool DriverIsProblematic(const char *driver)
*/
"dsp",
/* Jack isn't always configured properly on end user systems */
"jack",
/* OpenBSD sound API. Can be used on Linux, but very rare. */
"sndio",

View File

@@ -88,9 +88,19 @@ int hints_getHint(void *arg)
return TEST_COMPLETED;
}
typedef struct {
char *name;
char *value;
char *oldValue;
} HintCallbackContext;
static void SDLCALL hints_testHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
*(char **)userdata = hint ? SDL_strdup(hint) : NULL;
HintCallbackContext *context = userdata;
context->name = name ? SDL_strdup(name) : NULL;
context->value = hint ? SDL_strdup(hint) : NULL;
context->oldValue = oldValue ? SDL_strdup(oldValue) : NULL;
}
/**
@@ -102,7 +112,7 @@ int hints_setHint(void *arg)
const char *originalValue;
char *value;
const char *testValue;
char *callbackValue;
HintCallbackContext callback_data;
SDL_bool result;
int i, j;
@@ -152,8 +162,10 @@ int hints_setHint(void *arg)
SDLTest_AssertPass("Call to SDL_GetHint() after saving and restoring hint");
originalValue = SDL_GetHint(testHint);
value = (originalValue == NULL) ? NULL : SDL_strdup(originalValue);
SDL_SetHint(testHint, "temp");
SDL_SetHint(testHint, value);
result = SDL_SetHint(testHint, "temp");
SDLTest_AssertCheck(!result, "SDL_SetHint(\"%s\", \"temp\") should return false", testHint);
result = SDL_SetHint(testHint, value);
SDLTest_AssertCheck(!result, "SDL_SetHint(\"%s\", \"%s\" should return false", testHint, value);
SDL_free(value);
testValue = SDL_GetHint(testHint);
SDLTest_AssertCheck(
@@ -162,15 +174,26 @@ int hints_setHint(void *arg)
testValue);
SDLTest_AssertPass("Call to SDL_SetHintWithPriority(NULL, SDL_HINT_DEFAULT)");
SDL_SetHintWithPriority(testHint, NULL, SDL_HINT_DEFAULT);
result = SDL_SetHintWithPriority(testHint, NULL, SDL_HINT_DEFAULT);
SDLTest_AssertCheck(!result, "SDL_SetHintWithPriority(\"%s\", NULL, SDL_HINT_DEFAULT) should return false", testHint);
testValue = SDL_GetHint(testHint);
SDLTest_AssertCheck(
testValue && SDL_strcmp(testValue, "original") == 0,
"testValue = %s, expected \"original\"",
testValue);
SDLTest_AssertPass("Call to SDL_SetHint(\"\", \"data\")");
result = SDL_SetHint("", "data");
SDLTest_AssertCheck(result, "SDL_SetHint(\"\", \"data\") should return true");
testValue = SDL_GetHint("");
SDLTest_AssertCheck(
testValue && SDL_strcmp(testValue, "data") == 0,
"testValue = %s, expected \"data\"",
testValue);
SDLTest_AssertPass("Call to SDL_SetHintWithPriority(\"temp\", SDL_HINT_OVERRIDE)");
SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE);
result = SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE);
SDLTest_AssertCheck(result, "SDL_SetHintWithPriority(\"%s\", \"temp\", SDL_HINT_OVERRIDE) should return true", testHint);
testValue = SDL_GetHint(testHint);
SDLTest_AssertCheck(
testValue && SDL_strcmp(testValue, "temp") == 0,
@@ -178,7 +201,8 @@ int hints_setHint(void *arg)
testValue);
SDLTest_AssertPass("Call to SDL_SetHintWithPriority(NULL, SDL_HINT_OVERRIDE)");
SDL_SetHintWithPriority(testHint, NULL, SDL_HINT_OVERRIDE);
result = SDL_SetHintWithPriority(testHint, NULL, SDL_HINT_OVERRIDE);
SDLTest_AssertCheck(result, "SDL_SetHintWithPriority(\"%s\", NULL, SDL_HINT_OVERRIDE) should return true", testHint);
testValue = SDL_GetHint(testHint);
SDLTest_AssertCheck(
testValue == NULL,
@@ -194,49 +218,75 @@ int hints_setHint(void *arg)
testValue);
/* Make sure callback functionality works past a reset */
SDL_zero(callback_data);
SDLTest_AssertPass("Call to SDL_AddHintCallback()");
callbackValue = NULL;
SDL_AddHintCallback(testHint, hints_testHintChanged, &callbackValue);
SDL_AddHintCallback(testHint, hints_testHintChanged, &callback_data);
SDLTest_AssertCheck(
callbackValue && SDL_strcmp(callbackValue, "original") == 0,
"callbackValue = %s, expected \"original\"",
callbackValue);
SDL_free(callbackValue);
SDLTest_AssertPass("Call to SDL_SetHintWithPriority(\"temp\", SDL_HINT_OVERRIDE), using callback");
callbackValue = NULL;
SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE);
callback_data.name && SDL_strcmp(callback_data.name, testHint) == 0,
"callback_data.name = \"%s\", expected \"%s\"",
callback_data.name, testHint);
SDLTest_AssertCheck(
callbackValue && SDL_strcmp(callbackValue, "temp") == 0,
"callbackValue = %s, expected \"temp\"",
callbackValue);
SDL_free(callbackValue);
callback_data.value && SDL_strcmp(callback_data.value, "original") == 0,
"callback_data.value = \"%s\", expected \"%s\"",
callback_data.value, "original");
SDL_free(callback_data.name);
SDL_free(callback_data.value);
SDL_free(callback_data.oldValue);
SDLTest_AssertPass("Call to SDL_ResetHint(), using callback");
callbackValue = NULL;
SDL_zero(callback_data);
SDL_ResetHint(testHint);
SDLTest_AssertCheck(
callbackValue && SDL_strcmp(callbackValue, "original") == 0,
callback_data.value && SDL_strcmp(callback_data.value, "original") == 0,
"callbackValue = %s, expected \"original\"",
callbackValue);
callback_data.value);
SDL_free(callback_data.name);
SDL_free(callback_data.value);
SDL_free(callback_data.oldValue);
SDLTest_AssertPass("Call to SDL_SetHintWithPriority(\"temp\", SDL_HINT_OVERRIDE), using callback after reset");
callbackValue = NULL;
SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE);
SDL_zero(callback_data);
result = SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE);
SDLTest_AssertCheck(result, "SDL_SetHintWithPriority(\"%s\", \"temp\", SDL_HINT_OVERRIDE) should return true", testHint);
SDLTest_AssertCheck(
callbackValue && SDL_strcmp(callbackValue, "temp") == 0,
callback_data.value && SDL_strcmp(callback_data.value, "temp") == 0,
"callbackValue = %s, expected \"temp\"",
callbackValue);
SDL_free(callbackValue);
callback_data.value);
SDL_free(callback_data.name);
SDL_free(callback_data.value);
SDL_free(callback_data.oldValue);
SDLTest_AssertPass("Call to SDL_ResetHint(), after clearing callback");
callbackValue = NULL;
SDL_DelHintCallback(testHint, hints_testHintChanged, &callbackValue);
SDL_zero(callback_data);
SDL_DelHintCallback(testHint, hints_testHintChanged, &callback_data);
SDL_ResetHint(testHint);
SDLTest_AssertCheck(
callbackValue == NULL,
!callback_data.value,
"callbackValue = %s, expected \"(null)\"",
callbackValue);
callback_data.value);
SDL_free(callback_data.name);
SDL_free(callback_data.value);
SDL_free(callback_data.oldValue);
/* Make sure callback functionality work with hint renamed in sdl3 */
SDLTest_AssertPass("Call to SDL_AddHintCallback()");
SDL_AddHintCallback(SDL_HINT_ALLOW_TOPMOST, hints_testHintChanged, &callback_data);
SDLTest_AssertPass("Call to SDL_SetHintWithPriority(\"temp\", SDL_HINT_OVERRIDE), using callback");
SDL_zero(callback_data);
result = SDL_SetHintWithPriority(SDL_HINT_ALLOW_TOPMOST, "temp", SDL_HINT_OVERRIDE);
SDLTest_AssertCheck(result, "SDL_SetHintWithPriority(\"%s\", \"temp\", SDL_HINT_OVERRIDE) should return true", testHint);
SDLTest_AssertCheck(
callback_data.name && SDL_strcmp(callback_data.name, SDL_HINT_ALLOW_TOPMOST) == 0,
"callback_data.name = \"%s\", expected \"%s\"",
callback_data.name, SDL_HINT_ALLOW_TOPMOST);
SDLTest_AssertCheck(
callback_data.value && SDL_strcmp(callback_data.value, "temp") == 0,
"callback_data.value = \"%s\", expected \"%s\"",
callback_data.value, "temp");
SDL_free(callback_data.name);
SDL_free(callback_data.value);
SDL_free(callback_data.oldValue);
SDL_ResetHint(testHint);
return TEST_COMPLETED;
}

View File

@@ -12,6 +12,38 @@
/* Helper functions */
/* !
* \brief Private helper to check SDL_FRect equality
*/
static SDL_bool IsFRectEqual(const SDL_FRect *r1, const SDL_FRect *r2) {
static const float MAX_DELTA = 1e-5f;
SDL_FRect delta;
delta.x = r1->x - r2->x;
delta.y = r1->y - r2->y;
delta.w = r1->w - r2->w;
delta.h = r1->h - r2->h;
return -MAX_DELTA <= delta.x && delta.x <= MAX_DELTA
&& -MAX_DELTA <= delta.y && delta.y <= MAX_DELTA
&& -MAX_DELTA <= delta.w && delta.w <= MAX_DELTA
&& -MAX_DELTA <= delta.w && delta.h <= MAX_DELTA;
}
/* !
* \brief Private helper to check SDL_FPoint equality
*/
static SDL_bool IsFPointEqual(const SDL_FPoint *p1, const SDL_FPoint *p2) {
static const float MAX_DELTA = 1e-5f;
SDL_FPoint delta;
delta.x = p1->x - p2->x;
delta.y = p1->y - p2->y;
return -MAX_DELTA <= delta.x && delta.x <= MAX_DELTA
&& -MAX_DELTA <= delta.y && delta.y <= MAX_DELTA;
}
/* Helper functions */
/* !
* \brief Private helper to check SDL_IntersectRectAndLine results
*/
@@ -1698,6 +1730,226 @@ int rect_testFRectEqualsParam(void *arg)
return TEST_COMPLETED;
}
/* !
* \brief Test SDL_HasIntersectionF
*
* \sa
* http://wiki.libsdl.org/SDL2/SDL_HasIntersectionF
*/
int rect_testHasIntersectionF(void *arg)
{
const struct {
SDL_FRect r1;
SDL_FRect r2;
SDL_bool expected;
} cases[] = {
{ { 0, 0, 0, 0 }, {0, 0, 0, 0}, SDL_FALSE },
{ { 0, 0, -200, 200 }, {0, 0, -200, 200}, SDL_FALSE },
{ { 0, 0, 10, 10 }, {-5, 5, 10, 2}, SDL_TRUE },
{ { 0, 0, 10, 10 }, {-5, -5, 10, 2}, SDL_FALSE },
{ { 0, 0, 10, 10 }, {-5, -5, 2, 10}, SDL_FALSE },
{ { 0, 0, 10, 10 }, {-5, -5, 5, 5}, SDL_FALSE },
{ { 0, 0, 10, 10 }, {-5, -5, 5.1f, 5.1f}, SDL_TRUE },
{ { 0, 0, 10, 10 }, {-4.99f, -4.99f, 5, 5}, SDL_TRUE },
};
size_t i;
for (i = 0; i < SDL_arraysize(cases); i++) {
SDL_bool result;
SDLTest_AssertPass("About to call SDL_HasIntersectionF(&{ %g, %g, %g, %g }, &{ %g, %g, %g, %g })",
cases[i].r1.x, cases[i].r1.y, cases[i].r1.w, cases[i].r1.h,
cases[i].r2.x, cases[i].r2.y, cases[i].r2.w, cases[i].r2.h
);
result = SDL_HasIntersectionF(&cases[i].r1, &cases[i].r2);
SDLTest_AssertCheck(result == cases[i].expected, "Got %d, expected %d", result, cases[i].expected);
}
return TEST_COMPLETED;
}
/* !
* \brief Test SDL_IntersectFRect
*
* \sa
* http://wiki.libsdl.org/SDL2/SDL_IntersectFRect
*/
int rect_testIntersectFRect(void *arg)
{
const struct {
SDL_FRect r1;
SDL_FRect r2;
SDL_bool result;
SDL_FRect intersect;
} cases[] = {
{ { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, SDL_FALSE },
{ { 0, 0, -200, 200 }, { 0, 0, -200, 200 }, SDL_FALSE },
{ { 0, 0, 10, 10 }, { -5, 5, 9.9f, 2 }, SDL_TRUE, { 0, 5, 4.9f, 2 } },
{ { 0, 0, 10, 10 }, { -5, -5, 10, 2 }, SDL_FALSE},
{ { 0, 0, 10, 10 }, { -5, -5, 2, 10 }, SDL_FALSE},
{ { 0, 0, 10, 10 }, { -5, -5, 5, 5 }, SDL_FALSE},
{ { 0, 0, 10, 10 }, { -5, -5, 5.5f, 6 }, SDL_TRUE, { 0, 0, 0.5f, 1 } }
};
size_t i;
for (i = 0; i < SDL_arraysize(cases); i++) {
SDL_bool result;
SDL_FRect intersect;
SDLTest_AssertPass("About to call SDL_IntersectFRect(&{ %g, %g, %g, %g }, &{ %g, %g, %g, %g })",
cases[i].r1.x, cases[i].r1.y, cases[i].r1.w, cases[i].r1.h,
cases[i].r2.x, cases[i].r2.y, cases[i].r2.w, cases[i].r2.h
);
result = SDL_IntersectFRect(&cases[i].r1, &cases[i].r2, &intersect);
SDLTest_AssertCheck(result == cases[i].result, "Got %d, expected %d", result, cases[i].result);
if (cases[i].result) {
SDLTest_AssertCheck(IsFRectEqual(&intersect, &cases[i].intersect),
"Got { %g, %g, %g, %g }, expected { %g, %g, %g, %g }",
intersect.x, intersect.y, intersect.w, intersect.h,
cases[i].intersect.x, cases[i].intersect.y, cases[i].intersect.w, cases[i].intersect.h);
}
}
return TEST_COMPLETED;
}
/* !
* \brief Test SDL_UnionFRect
*
* \sa
* http://wiki.libsdl.org/SDL2/SDL_UnionFRect
*/
int rect_testUnionFRect(void *arg)
{
const struct {
SDL_FRect r1;
SDL_FRect r2;
SDL_FRect expected;
} cases[] = {
{ { 0, 0, 10, 10 }, { 19.9f, 20, 10, 10 }, { 0, 0, 29.9f, 30 } },
{ { 0, 0, 0, 0 }, { 20, 20.1f, 10.1f, 10 }, { 20, 20.1f, 10.1f, 10 } },
{ { -200, -4.5f, 450, 33 }, { 20, 20, 10, 10 }, { -200, -4.5f, 450, 34.5f } },
{ { 0, 0, 15, 16.5f }, { 20, 20, 0, 0 }, { 0, 0, 15, 16.5f } }
};
size_t i;
for (i = 0; i < SDL_arraysize(cases); i++) {
SDL_FRect result;
SDLTest_AssertPass("About to call SDL_UnionFRect(&{ %g, %g, %g, %g }, &{ %g, %g, %g, %g })",
cases[i].r1.x, cases[i].r1.y, cases[i].r1.w, cases[i].r1.h,
cases[i].r2.x, cases[i].r2.y, cases[i].r2.w, cases[i].r2.h
);
SDL_UnionFRect(&cases[i].r1, &cases[i].r2, &result);
SDLTest_AssertCheck(IsFRectEqual(&result, &cases[i].expected),
"Got { %g, %g, %g, %g }, expected { %g, %g, %g, %g }",
result.x, result.y, result.w, result.h,
cases[i].expected.x, cases[i].expected.y, cases[i].expected.w, cases[i].expected.h);
}
return TEST_COMPLETED;
}
/* !
* \brief Test SDL_EncloseFPointsUnionFRect
*
* \sa
* http://wiki.libsdl.org/SDL2/SDL_EncloseFPoints
*/
int rect_testEncloseFPoints(void *arg)
{
const struct {
SDL_bool with_clip;
SDL_FRect clip;
SDL_bool result;
SDL_FRect enclosing;
} cases[] = {
{ SDL_TRUE, { 0, 0, 10, 10 }, SDL_TRUE, { 0.5f, 0.1f, 6, 8 }},
{ SDL_TRUE, { 1.2f, 1, 10, 10 }, SDL_TRUE, { 1.5f, 1.1f, 5, 7 }},
{ SDL_TRUE, { -10, -10, 3, 3 }, SDL_FALSE },
{ SDL_FALSE, { 0 }, SDL_TRUE, { 0.5, 0.1f, 6, 8 }}
};
const SDL_FPoint points[] = {
{ 0.5f, 0.1f },
{ 5.5f, 7.1f },
{ 1.5f, 1.1f }
};
char points_str[256];
size_t i;
SDL_strlcpy(points_str, "{", sizeof(points_str));
for (i = 0; i < SDL_arraysize(points); i++) {
char point_str[32];
SDL_snprintf(point_str, sizeof(point_str), "{ %g, %g }, ", points[i].x, points[i].y);
SDL_strlcat(points_str, point_str, sizeof(points_str));
}
SDL_strlcat(points_str, "}", sizeof(points_str));
for (i = 0; i < SDL_arraysize(cases); i++) {
char clip_str[64];
SDL_bool result;
SDL_FRect enclosing;
const SDL_FRect* clip_ptr = NULL;
if (cases[i].with_clip) {
SDL_snprintf(clip_str, sizeof(clip_str), "&{ %g, %g, %g, %g }",
cases[i].clip.x, cases[i].clip.y, cases[i].clip.w, cases[i].clip.h);
clip_ptr = &cases[i].clip;
} else {
SDL_strlcpy(clip_str, "NULL", sizeof(clip_str));
}
SDLTest_AssertPass("About to call SDL_EncloseFPoints(&%s, %d, %s)", points_str, (int)SDL_arraysize(points), clip_str);
result = SDL_EncloseFPoints(points, SDL_arraysize(points), clip_ptr, &enclosing);
SDLTest_AssertCheck(result == cases[i].result, "Got %d, expected %d", result, cases[i].result);
if (cases[i].result) {
SDLTest_AssertCheck(IsFRectEqual(&enclosing, &cases[i].enclosing),
"Got { %g, %g, %g, %g }, expected { %g, %g, %g, %g }",
enclosing.x, enclosing.y, enclosing.w, enclosing.h,
cases[i].enclosing.x, cases[i].enclosing.y, cases[i].enclosing.w, cases[i].enclosing.h);
}
}
return TEST_COMPLETED;
}
/* !
* \brief Test SDL_IntersectFRectAndLine
*
* \sa
* http://wiki.libsdl.org/SDL2/SDL_IntersectFRectAndLine
*/
int rect_testIntersectFRectAndLine(void *arg)
{
const struct {
SDL_FRect rect;
SDL_FPoint p1;
SDL_FPoint p2;
SDL_bool result;
SDL_FPoint expected1;
SDL_FPoint expected2;
} cases[] = {
{ { 0, 0, 0, 0 }, { -4.8f, -4.8f }, { 5.2f, 5.2f }, SDL_FALSE },
{ { 0, 0, 2, 2 }, { -1, -1 }, { 3.5f, 3.5f }, SDL_TRUE, { 0, 0 }, { 1, 1 } },
{ { -4, -4, 14, 14 }, { 8, 22 }, { 8, 33}, SDL_FALSE }
};
size_t i;
for (i = 0; i < SDL_arraysize(cases); i++) {
SDL_bool result;
SDL_FPoint p1 = cases[i].p1;
SDL_FPoint p2 = cases[i].p2;
SDLTest_AssertPass("About to call SDL_IntersectFRectAndLine(&{%g, %g, %g, %g}, &%g, &%g, &%g, &%g)",
cases[i].rect.x, cases[i].rect.y, cases[i].rect.w, cases[i].rect.h,
p1.x, p1.y, p2.x, p2.y);
result = SDL_IntersectFRectAndLine(&cases[i].rect, &p1.x, &p1.y, &p2.x, &p2.y);
SDLTest_AssertCheck(result == cases[i].result, "Got %d, expected %d", result, cases[i].result);
if (cases[i].result) {
SDLTest_AssertCheck(IsFPointEqual(&p1, &cases[i].expected1),
"Got p1={ %g, %g }, expected p1={ %g, %g }",
p1.x, p1.y,
cases[i].expected1.x, cases[i].expected1.y);
SDLTest_AssertCheck(IsFPointEqual(&p2, &cases[i].expected2),
"Got p2={ %g, %g }, expected p2={ %g, %g }",
p2.x, p2.y,
cases[i].expected2.x, cases[i].expected2.y);
}
}
return TEST_COMPLETED;
}
/* ================= Test References ================== */
/* Rect test cases */
@@ -1836,6 +2088,26 @@ static const SDLTest_TestCaseReference rectTest31 = {
(SDLTest_TestCaseFp)rect_testFRectEqualsParam, "rect_testFRectEqualsParam", "Negative tests against SDL_FRectEquals with invalid parameters", TEST_ENABLED
};
static const SDLTest_TestCaseReference rectTest32 = {
(SDLTest_TestCaseFp)rect_testHasIntersectionF, "rect_testHasIntersectionF", "Tests SDL_HasIntersectionF", TEST_ENABLED
};
static const SDLTest_TestCaseReference rectTest33 = {
(SDLTest_TestCaseFp)rect_testIntersectFRect, "rect_testIntersectFRect", "Tests SDL_IntersectFRect", TEST_ENABLED
};
static const SDLTest_TestCaseReference rectTest34 = {
(SDLTest_TestCaseFp)rect_testUnionFRect, "rect_testUnionFRect", "Tests SDL_UnionFRect", TEST_ENABLED
};
static const SDLTest_TestCaseReference rectTest35 = {
(SDLTest_TestCaseFp)rect_testEncloseFPoints, "rect_testEncloseFPoints", "Tests SDL_EncloseFPoints", TEST_ENABLED
};
static const SDLTest_TestCaseReference rectTest36 = {
(SDLTest_TestCaseFp)rect_testIntersectFRectAndLine, "rect_testIntersectFRectAndLine", "Tests SDL_IntersectFRectAndLine", TEST_ENABLED
};
/* !
* \brief Sequence of Rect test cases; functions that handle simple rectangles including overlaps and merges.
*
@@ -1845,7 +2117,7 @@ static const SDLTest_TestCaseReference rectTest31 = {
static const SDLTest_TestCaseReference *rectTests[] = {
&rectTest1, &rectTest2, &rectTest3, &rectTest4, &rectTest5, &rectTest6, &rectTest7, &rectTest8, &rectTest9, &rectTest10, &rectTest11, &rectTest12, &rectTest13, &rectTest14,
&rectTest15, &rectTest16, &rectTest17, &rectTest18, &rectTest19, &rectTest20, &rectTest21, &rectTest22, &rectTest23, &rectTest24, &rectTest25, &rectTest26, &rectTest27,
&rectTest28, &rectTest29, &rectTest30, &rectTest31, NULL
&rectTest28, &rectTest29, &rectTest30, &rectTest31, &rectTest32, &rectTest33, &rectTest34, &rectTest35, &rectTest36, NULL
};
/* Rect test suite (global) */

View File

@@ -811,6 +811,136 @@ int render_testBlitBlend(void *arg)
return TEST_COMPLETED;
}
static Uint32 read_surface_pixel32(SDL_Surface *surface, int x, int y) {
Uint32 result;
if (x >= surface->w || y >= surface->h) {
SDLTest_AssertCheck(x < surface->w, "x (%d) < surface->w (%d)", x, surface->w);
SDLTest_AssertCheck(y < surface->h, "y (%d) < surface->h (%d)", y, surface->h);
result = 0xdeadbabe;
} else {
SDL_memcpy(&result, (Uint8 *)surface->pixels + surface->pitch * y + surface->format->BytesPerPixel * x, sizeof(Uint32));
}
return result;
}
static int render_testRGBSurfaceNoAlpha(void* arg)
{
SDL_Surface *surface;
SDL_Renderer *software_renderer;
SDL_Surface *surface2;
SDL_Texture *texture2;
int result;
SDL_Rect dest_rect;
SDL_Point point;
Uint32 pixel;
SDLTest_AssertPass("About to call SDL_CreateRGBSurface(0, 128, 128, 32, 0xff0000, 0xff00, 0xff, 0)");
surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0xff0000, 0xff00, 0xff, 0);
SDLTest_AssertCheck(surface != NULL, "Returned surface must be not NULL");
SDLTest_AssertCheck(surface->format->BitsPerPixel == 32, "surface->format->BitsPerPixel should be 32, actual value is %d", surface->format->BitsPerPixel);
SDLTest_AssertCheck(surface->format->BytesPerPixel == 4, "surface->format->BytesPerPixels should be 4, actual value is %d", surface->format->BytesPerPixel);
SDLTest_AssertPass("About to call SDL_CreateSoftwareRenderer(surface)");
software_renderer = SDL_CreateSoftwareRenderer(surface);
SDLTest_AssertCheck(software_renderer != NULL, "Returned renderer must be not NULL");
SDLTest_AssertPass("About to call SDL_CreateRGBSurface(0, 16, 16, 32, 0xff0000, 0xff00, 0xff, 0)");
surface2 = SDL_CreateRGBSurface(0, 16, 16, 32, 0xff0000, 0xff00, 0xff, 0);
SDLTest_AssertCheck(surface2 != NULL, "Returned surface must be not NULL");
SDLTest_AssertPass("About to call SDL_FillRect(surface2, NULL, 0)");
result = SDL_FillRect(surface2, NULL, SDL_MapRGB(surface2->format, 0, 0, 0));
SDLTest_AssertCheck(result == 0, "Result should be 0, actual value is %d", result);
SDLTest_AssertPass("About to call SDL_CreateTextureFromSurface(software_renderer, surface2)");
texture2 = SDL_CreateTextureFromSurface(software_renderer, surface2);
SDLTest_AssertCheck(texture2 != NULL, "Returned texture is not NULL");
SDLTest_AssertPass("About to call SDL_SetRenderDrawColor(renderer, 0xaa, 0xbb, 0xcc, 0x0)");
result = SDL_SetRenderDrawColor(software_renderer, 0xaa, 0xbb, 0xcc, 0x0);
SDLTest_AssertPass("About to call SDL_RenderClear(renderer)");
result = SDL_RenderClear(software_renderer);
SDLTest_AssertCheck(result == 0, "Result should be 0, actual value is %d", result);
SDLTest_AssertPass("About to call SDL_SetRenderDrawColor(renderer, 0x0, 0x0, 0x0, 0x0)");
result = SDL_SetRenderDrawColor(software_renderer, 0x0, 0x0, 0x0, 0x0);
SDLTest_AssertCheck(result == 0, "Result should be 0, actual value is %d", result);
dest_rect.x = 32;
dest_rect.y = 32;
dest_rect.w = surface2->w;
dest_rect.h = surface2->h;
point.x = 0;
point.y = 0;
SDLTest_AssertPass("About to call SDL_RenderCopy(software_renderer, texture, NULL, &{%d, %d, %d, %d})",
dest_rect.x, dest_rect.h, dest_rect.w, dest_rect.h);
result = SDL_RenderCopyEx(software_renderer, texture2, NULL, &dest_rect, 180, &point, SDL_FLIP_NONE);
SDLTest_AssertCheck(result == 0, "Result should be 0, actual value is %d", result);
SDLTest_AssertPass("About to call SDL_RenderPresent(software_renderer)");
SDL_RenderPresent(software_renderer);
pixel = read_surface_pixel32(surface, 0, 0);
SDLTest_AssertCheck(pixel == 0xAABBCCu, "Pixel at (0, 0) should be 0x%08x, actual value is 0x%08" SDL_PRIx32, 0xAABBCCu, pixel);
pixel = read_surface_pixel32(surface, 15, 15);
SDLTest_AssertCheck(pixel == 0xAABBCCu, "Pixel at (15, 15) should be 0x%08x, actual value is 0x%08" SDL_PRIx32, 0xAABBCCu, pixel);
pixel = read_surface_pixel32(surface, 16, 16);
SDLTest_AssertCheck(pixel == 0xFF000000u, "Pixel at (16, 16) should be 0x%08x, actual value is 0x%08" SDL_PRIx32, 0xFF000000u, pixel);
pixel = read_surface_pixel32(surface, 31, 31);
SDLTest_AssertCheck(pixel == 0xFF000000u, "Pixel at (31, 31) should be 0x%08x, actual value is 0x%08" SDL_PRIx32, 0xFF000000u, pixel);
pixel = read_surface_pixel32(surface, 32, 32);
SDLTest_AssertCheck(pixel == 0xAABBCCu, "Pixel at (32, 32) should be 0x%08x, actual value is 0x%08" SDL_PRIx32, 0xAABBCCu, pixel);
SDL_DestroyTexture(texture2);
SDL_FreeSurface(surface2);
SDL_DestroyRenderer(software_renderer);
SDL_FreeSurface(surface);
return TEST_COMPLETED;
}
/**
* @brief Tests setting and getting texture scale mode.
*
* \sa
* http://wiki.libsdl.org/SDL2/SDL_SetTextureScaleMode
* http://wiki.libsdl.org/SDL2/SDL_GetTextureScaleMode
*/
int render_testGetSetTextureScaleMode(void *arg)
{
const struct {
const char *name;
SDL_ScaleMode mode;
} modes[] = {
{ "SDL_ScaleModeNearest", SDL_ScaleModeNearest },
{ "SDL_ScaleModeLinear", SDL_ScaleModeLinear },
{ "SDL_ScaleModeBest", SDL_ScaleModeBest }
};
size_t i;
for (i = 0; i < SDL_arraysize(modes); i++) {
SDL_Texture *texture;
int result;
SDL_ScaleMode actual_mode = SDL_ScaleModeNearest;
SDL_ClearError();
SDLTest_AssertPass("About to call SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 16, 16)");
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 16, 16);
SDLTest_AssertCheck(texture != NULL, "SDL_CreateTexture must return a non-NULL texture");
SDLTest_AssertPass("About to call SDL_SetTextureScaleMode(texture, %s)", modes[i].name);
result = SDL_SetTextureScaleMode(texture, modes[i].mode);
SDLTest_AssertCheck(result == 0, "SDL_SetTextureScaleMode must return 0, actual %d", result);
SDLTest_AssertPass("About to call SDL_GetTextureScaleMode(texture)");
result = SDL_GetTextureScaleMode(texture, &actual_mode);
SDLTest_AssertCheck(result == 0, "SDL_SetTextureScaleMode must return 0, actual %d", result);
SDLTest_AssertCheck(actual_mode == modes[i].mode, "SDL_GetTextureScaleMode must return %s (%d), actual=%d",
modes[i].name, modes[i].mode, actual_mode);
}
return TEST_COMPLETED;
}
/**
* @brief Checks to see if functionality is supported. Helper function.
*/
@@ -1161,9 +1291,17 @@ static const SDLTest_TestCaseReference renderTest7 = {
(SDLTest_TestCaseFp)render_testBlitBlend, "render_testBlitBlend", "Tests blitting with blending", TEST_DISABLED
};
static const SDLTest_TestCaseReference renderTest8 = {
(SDLTest_TestCaseFp)render_testGetSetTextureScaleMode, "render_testGetSetTextureScaleMode", "Tests setting/getting texture scale mode", TEST_ENABLED
};
static const SDLTest_TestCaseReference renderTest9 = {
(SDLTest_TestCaseFp)render_testRGBSurfaceNoAlpha, "render_testRGBSurfaceNoAlpha", "Tests RGB surface with no alpha using software renderer", TEST_ENABLED
};
/* Sequence of Render test cases */
static const SDLTest_TestCaseReference *renderTests[] = {
&renderTest1, &renderTest2, &renderTest3, &renderTest4, &renderTest5, &renderTest6, &renderTest7, NULL
&renderTest1, &renderTest2, &renderTest3, &renderTest4, &renderTest5, &renderTest6, &renderTest7, &renderTest8, &renderTest9, NULL
};
/* Render test suite (global) */

View File

@@ -393,6 +393,7 @@ int stdlib_getsetenv(void *arg)
#endif
#define FMT_PRILLd "%lld"
#define FMT_PRILLdn "%lld%lln"
#define FMT_PRILLu "%llu"
/**
@@ -403,13 +404,15 @@ int stdlib_sscanf(void *arg)
{
int output;
int result;
int length;
int expected_output;
int expected_result;
short short_output, expected_short_output;
long long_output, expected_long_output;
long long long_long_output, expected_long_long_output;
short short_output, expected_short_output, short_length;
long long_output, expected_long_output, long_length;
long long long_long_output, expected_long_long_output, long_long_length;
size_t size_output, expected_size_output;
char text[128], text2[128];
unsigned int r = 0, g = 0, b = 0;
expected_output = output = 123;
expected_result = -1;
@@ -426,43 +429,62 @@ int stdlib_sscanf(void *arg)
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
output = 123;
length = 0;
expected_output = 2;
expected_result = 1;
result = SDL_sscanf("2", "%i", &output);
SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i\", &output)");
result = SDL_sscanf("2", "%i%n", &output, &length);
SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i%%n\", &output, &length)");
SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
SDLTest_AssertCheck(length == 1, "Check length, expected: 1, got: %i", length);
output = 123;
length = 0;
expected_output = 0xa;
expected_result = 1;
result = SDL_sscanf("aa", "%1x", &output);
SDLTest_AssertPass("Call to SDL_sscanf(\"aa\", \"%%1x\", &output)");
result = SDL_sscanf("aa", "%1x%n", &output, &length);
SDLTest_AssertPass("Call to SDL_sscanf(\"aa\", \"%%1x%%n\", &output, &length)");
SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
SDLTest_AssertCheck(length == 1, "Check length, expected: 1, got: %i", length);
#define SIZED_TEST_CASE(type, var, format_specifier) \
var##_output = 123; \
expected_##var##_output = (type)(((unsigned type)(~0)) >> 1); \
expected_result = 1; \
result = SDL_snprintf(text, sizeof(text), format_specifier, expected_##var##_output); \
result = SDL_sscanf(text, format_specifier, &var##_output); \
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%s\", &output)", text, #format_specifier); \
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " format_specifier ", got: " format_specifier, expected_##var##_output, var##_output); \
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
\
var##_output = 123; \
expected_##var##_output = ~(type)(((unsigned type)(~0)) >> 1); \
expected_result = 1; \
result = SDL_snprintf(text, sizeof(text), format_specifier, expected_##var##_output); \
result = SDL_sscanf(text, format_specifier, &var##_output); \
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%s\", &output)", text, #format_specifier); \
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " format_specifier ", got: " format_specifier, expected_##var##_output, var##_output); \
expected_result = 3;
result = SDL_sscanf("#026", "#%1x%1x%1x", &r, &g, &b);
SDLTest_AssertPass("Call to SDL_sscanf(\"#026\", \"#%%1x%%1x%%1x\", &r, &g, &b)");
expected_output = 0;
SDLTest_AssertCheck(r == expected_output, "Check output for r, expected: %i, got: %i", expected_output, r);
expected_output = 2;
SDLTest_AssertCheck(g == expected_output, "Check output for g, expected: %i, got: %i", expected_output, g);
expected_output = 6;
SDLTest_AssertCheck(b == expected_output, "Check output for b, expected: %i, got: %i", expected_output, b);
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
SIZED_TEST_CASE(short, short, "%hd")
SIZED_TEST_CASE(long, long, "%ld")
SIZED_TEST_CASE(long long, long_long, "%lld")
#define SIZED_TEST_CASE(type, var, printf_specifier, scanf_specifier) \
var##_output = 123; \
var##_length = 0; \
expected_##var##_output = (type)(((unsigned type)(~0)) >> 1); \
expected_result = 1; \
result = SDL_snprintf(text, sizeof(text), printf_specifier, expected_##var##_output); \
result = SDL_sscanf(text, scanf_specifier, &var##_output, &var##_length); \
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", %s, &output, &length)", text, #scanf_specifier); \
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " printf_specifier ", got: " printf_specifier, expected_##var##_output, var##_output); \
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
SDLTest_AssertCheck(var##_length == (type)SDL_strlen(text), "Check length, expected: %i, got: %i", (int)SDL_strlen(text), (int)var##_length); \
\
var##_output = 123; \
var##_length = 0; \
expected_##var##_output = ~(type)(((unsigned type)(~0)) >> 1); \
expected_result = 1; \
result = SDL_snprintf(text, sizeof(text), printf_specifier, expected_##var##_output); \
result = SDL_sscanf(text, scanf_specifier, &var##_output, &var##_length); \
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", %s, &output, &length)", text, #scanf_specifier); \
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " printf_specifier ", got: " printf_specifier, expected_##var##_output, var##_output); \
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
SDLTest_AssertCheck(var##_length == (type)SDL_strlen(text), "Check length, expected: %i, got: %i", (int)SDL_strlen(text), (int)var##_length); \
SIZED_TEST_CASE(short, short, "%hd", "%hd%hn")
SIZED_TEST_CASE(long, long, "%ld", "%ld%ln")
SIZED_TEST_CASE(long long, long_long, FMT_PRILLd, FMT_PRILLdn)
size_output = 123;
expected_size_output = ~((size_t)0);

View File

@@ -208,6 +208,42 @@ static int subsystems_dependRefCountWithExtraInit(void)
return TEST_COMPLETED;
}
/**
* \brief Inits and Quits timers subsystem, which cannot be explicitly initialized in SDL3
*
* \sa SDL_InitSubSystem
* \sa SDL_QuitSubSystem
*
*/
static int subsystems_timersSubsystem(void)
{
int result;
/* Ensure that we start with reset subsystems. */
SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0,
"Check result from SDL_WasInit(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)");
SDLTest_AssertPass("About to call SDL_WasInit(0)");
result = SDL_WasInit(0);
SDLTest_AssertCheck(result == 0, "SDL_WasInit(0) should return 0, actual 0x%x", result);
SDLTest_AssertPass("About to call SDL_InitSubSystem(SDL_INIT_TIMER)");
result = SDL_InitSubSystem(SDL_INIT_TIMER);
SDLTest_AssertCheck(result == 0, "Must return 0, actually %d", result);
SDLTest_AssertPass("About to call SDL_WasInit(SDL_INIT_TIMER)");
result = SDL_WasInit(SDL_INIT_TIMER);
SDLTest_AssertCheck(result == SDL_INIT_TIMER, "Must return SDL_INIT_TIMER (=%d), actually %d", SDL_INIT_TIMER, result);
SDLTest_AssertPass("About to call SDL_WasInit(0)");
result = SDL_WasInit(0);
SDLTest_AssertCheck(result == SDL_INIT_TIMER, "SDL_WasInit(0) should return SDL_INIT_TIMER, actual 0x%x", result);
SDLTest_AssertPass("About to call SDL_QuitSubSystem(SDL_INIT_TIMER)");
SDL_QuitSubSystem(SDL_INIT_TIMER);
SDLTest_AssertPass("SDL_QuitSubSystem finished");
return TEST_COMPLETED;
}
/* ================= Test References ================== */
/* Subsystems test cases */
@@ -227,9 +263,13 @@ static const SDLTest_TestCaseReference subsystemsTest4 = {
(SDLTest_TestCaseFp)subsystems_dependRefCountWithExtraInit, "subsystems_dependRefCountWithExtraInit", "Check reference count of subsystem dependencies.", TEST_ENABLED
};
static const SDLTest_TestCaseReference subsystemsTest5 = {
(SDLTest_TestCaseFp)subsystems_timersSubsystem, "subsystems_timersSubsystem", "Check timer subsystem, removed in SDL3.", TEST_ENABLED
};
/* Sequence of Events test cases */
static const SDLTest_TestCaseReference *subsystemsTests[] = {
&subsystemsTest1, &subsystemsTest2, &subsystemsTest3, &subsystemsTest4, NULL
&subsystemsTest1, &subsystemsTest2, &subsystemsTest3, &subsystemsTest4, &subsystemsTest5, NULL
};
/* Events test suite (global) */

View File

@@ -2251,6 +2251,33 @@ static int video_getWindowSurface(void *arg)
return TEST_COMPLETED;
}
/**
* Tests SDL_SetWindowInputFocus
*/
static int video_setWindowInputFocus(void *arg)
{
int result;
SDL_Window *window;
SDLTest_AssertPass("SDL_SetWindowInputFocus is not supported on dummy and SDL2 wayland driver");
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "dummy") == 0 || SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) {
return TEST_SKIPPED;
}
window = _createVideoSuiteTestWindow("video_setWindowInputFocus");
if (!window) {
return TEST_ABORTED;
}
SDLTest_AssertPass("About to call SDL_SetWindowInputFocus(window)");
result = SDL_SetWindowInputFocus(window);
SDLTest_AssertCheck(result == 0, "Result is %d, expected 0", result);
_destroyVideoSuiteTestWindow(window);
return TEST_COMPLETED;
}
/* ================= Test References ================== */
/* Video test cases */
@@ -2338,6 +2365,9 @@ static const SDLTest_TestCaseReference videoTest24 =
static const SDLTest_TestCaseReference videoTest25 = {
(SDLTest_TestCaseFp)video_getWindowSurface, "video_getWindowSurface", "Checks window surface functionality", TEST_ENABLED
};
static const SDLTest_TestCaseReference videoTest26 = {
(SDLTest_TestCaseFp)video_setWindowInputFocus, "video_setWindowInputFocus", "Checks window input focus", TEST_ENABLED
};
/* Sequence of Video test cases */
static const SDLTest_TestCaseReference *videoTests[] = {
@@ -2345,7 +2375,7 @@ static const SDLTest_TestCaseReference *videoTests[] = {
&videoTest7, &videoTest8, &videoTest9, &videoTest10, &videoTest11, &videoTest12,
&videoTest13, &videoTest14, &videoTest15, &videoTest16, &videoTest17,
&videoTest18, &videoTest19, &videoTest20, &videoTest21, &videoTest22,
&videoTest23, &videoTest24, &videoTest25, NULL
&videoTest23, &videoTest24, &videoTest25, &videoTest26, NULL
};
/* Video test suite (global) */