Squashed 'external/SDL/' changes from 90fd2a3cbe..279dabfc96

279dabfc96 cocoa: Don't use trick of briefly focusing the Dock on newer macOS releases.
afa27243df Ignore sensor delta values that look like they're out of range
cd98b66114 Allow overriding SDL_FORK_MESSAGEBOX in build environment
8d5bf053f7 Fixed detecting 8BitDo sensor timestamp on older firmware
0ac1241b7a x11: Always update the borders on frame extent events
f40bf44928 Removed unnecessary include
6d3e8b749e add 8BitDo Controller sensor_timestamp (#13278)
727b4924c8 Update the viewport when logical presentation changes
de6a23028a Fix #13276: Crash in SDL_GetAudioDeviceChannelMap
8442d4f0f7 joystick: Add support Xbox Adaptive Controller
3cd979b353 SDL_render.h: enum SDL_TextureAddressMode: Removed trailing comma
db3a35e9bc joystick: Fix MSVC errors C2099 with `/fp:strict`
9ed83e71f6 Fixed memory leaks in KMSDRM property handling
603118c340 Sync SDL3 wiki -> header
aa4f916b71 Renamed SDL_PROP_AUDIOSTREAM_KEEP_ON_SHUTDOWN_BOOLEAN to SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN
6cfe211142 Sync SDL3 wiki -> header
274aa0242e audio: Let apps save an audio stream from destruction during SDL_Quit(). (#13244)
af8bee2dd1 alsa: change an SDL_LogError into SDL_LogDebug.
bbc674b9e7 test: Fix resource paths in testtray
796961acec Resolve bug for calibration Nintendo Switch Pro Controller (#13260)
3a6f9e01f8 Fixed Nintendo Switch thumbstick calibration
038a3806eb Fixed Nintendo Switch Pro thumbstick calibration
e6c2649afc Updated testffmpeg for ffmpeg 7.1
e80d084766 expose events originating from a live-resize set the data1 field to 1.
6aedc488d3 win32: Invalidate window message mouse button flags when reading buttons from raw input or GameInput
81e3066303 hidapi/libusb: disable C5287 warning in MSVC builds
7d9fd48557 alsa: recover from snd_pcm_avail() returning -EPIPE
e68f5ca99a alsa: use udev if available instead of a hotplug thread
051ce0ff89 alsa: fixed disconnecting the microphone when opened
5fcc83d93b Vita Render: Limit the scope of cliprect to viewport
1bd5110ff0 Vita: Fixed absence of clipping when viewport is set
eb04219efe audio: Enumerating audio devices will skip zombie devices still in the hash.
d06b6e42d2 Sync SDL3 wiki -> header
c19ad189dc Clarify that SDL_GetAudioStreamDevice() returns the logical device.
7882e60f0e Don't log an error for disconnected audio devices
e4e29b8601 Fix support for F21 to F24 scancodes on Linux
d7939abf42 Use consistent style for pointer declarations and casts
390fe65323 test: Fix a window parenting bug in testmodal
ca9b7c8ea3 video: Explicitly disallow setting the parent of a window to itself
c04624972e alsa: Simplify ALSA_WaitDevice.
b4ac5f43f5 include: Fixed copy/paste error in endian-specific SDL_Read function docs.
3896b1b3f4 wikiheaders: Let each subproject specify how to find their property symbols.
efed3c63b3 Added support for an alternate version of the Vader 4 Pro
d6bae53341 Added support for an alternate version of the Vader 4 Pro
f62c982bcf Reverted Accelerometer and Gyro displays to throttled display (10hz)
b833c618a9 Improved reliability detecting FlyDigi Vader controllers
0e262dfd44 Sync SDL3 wiki -> header
6c406dd122 include: a couple of documentation tweaks and typo fixes.
42c9fe119d Sync SDL3 wiki -> header
f5d1402c28 Flydigi Vader 4 Pro IMU rate correction (#13215)
1e886c8a2f 8 bitdo polling rate corrections (#13221)
913b611ccd Added tools for evaluating gyroscope accuracy and IMU polling rates. (#13209)
e2239c36d3 wayland: Ensure that the tablet tool list is always initialized to empty
ec1297199e wayland: Implement the pointer warp protocol
558a89fdb6 Read Switch controller gyro/accel sensitivity coeffs (SDL3)
fd4ffa6d27 Sync SDL3 wiki -> header
c5b1341757 Tweak Vulkan include guard check and 64-bit platform defines (#13210)
e18a6313de Added gyro support for the Flydigi Vader 3 Pro controller
71f479b4aa Fix a broken link inside README-cmake.md that's meant to send to README-linux.md also made said link more consistent with other links by adding .md suffix
f2bcfe3dd2 Correct the texture format used for the N-Gage (#13192)
685f1720fe Revert "[Nokia N-Gage] Fix alpha transparency in 4K color mode using BitBltMasked"
a89a20a9ab Fix Markdown typo in Arch Linux dependencies docs
cbc9d662ea [Nokia N-Gage] Add define to disable FPS counter by default.
d9af41b5ac cmake: more private definitions
5826966873 Fixed replacing existing specific gamepad mappings
f90a21483c Added support for the ZEROPLUS P4 Wired Gamepad
638acdc02a Remove the CRC from automatically generated gamepad mappings
45eb6310a8 x11: Resize fixed-size windows after mapping on xmonad
7dd5e765df joystick: Report battery on GIP controllers
c54a017f47 joystick: Clean up Elite Button handling
559efd58e2 joystick: Add headset stub to GIP driver
7cc3feeb1b keyboard: Search for the correct base key value when querying the keycode from a scancode
22fa45b3c1 win32: Ensure that text input is initially disabled when creating a window
c240ed976f Sync SDL3 wiki -> header
27464ffb08 Clarify that icon and cursor alternate images are added with SDL_AddSurfaceAlternateImage()
2ef7944170 [Nokia N-Gage] Fix alpha transparency in 4K color mode using BitBltMasked
d86fb8a83a gdk: Ignore focus loss events caused by text input showing the OSK
6622f4e1ea Added support for the NACON Revolution X Unlimited controller on macOS
45aa497813 [Nokia N-Gage] Fix SDL_GetPerformanceFrequency and SDL_GetPerformanceCounter
7457857304 Fixed input from the MayFlash GameCube adapter with version 7 firmware
1ec12b38e5 Sync SDL3 wiki -> header
b6c4a46b85 workflows: Use stable Steam Runtime 3 on both x86_64 and arm64
fbba5b272a GPU: Binding validation and prevent null dereference if expected binding is missing (#13164)
cf6c42e6e6 Use HEAPU8.set rather than Module.HEAPU8.set (thanks @sbc100!)
4b0f48c4cf Mark gamepads as invalid if they can't be opened
a314a58e7e Sync SDL3 wiki -> header
d283f4651c Sync SDL3 wiki -> header
8510331f66 .wikiheaders-options: Add Tray to quickreference categories.
b8187e2abd wikiheaders: Trim whitespace from end of lines in section headers.
9e0d9f30a7 x11: Be a little less aggressive with Xinput2IsInitialized checks.
57b6e6c7f9 Checks if xinput is loaded before trying to call xinput functions
ac3ab026fe audio: corrected comment about device format minimums.
83cc3bc234 audio: Opened device spec must be >= simple minimums, not device's defaults.
14a4ae521a pulseaudio: Request more recording data per-fragment.
3a4de2ad89 Sync SDL3 wiki -> header
47717f22fd cocoa: Always add a window-sized NSTrackingArea to each window.
f61d956a04 cocoa: add explicit tracking areas to the window.
58afb0d8ae wayland: Update xkbcommon names and types
c764e8864b wayland: Update xkbcommon to avoid using deprecated modifier names
b61586b492 [Nokia N-Gage] Increase max. texture size from 256 to 1024; the previous setting was chosen at random and does not necessarily make sense in practice.
329b5f27d6 fix preprocessor directive for SDL_RESTRICT definition in C99 case.
0d58594e66 fix inverted __STDC_VERSION__ condition in SDL_RESTRICT definition.
6a686185f7 SDL_begin_code.h: Actually define SDL_RESTRICT.
51dfca813b Pass text input rect to steam deck keyboard invocation
520d73ae57 include/SDL_gpu: fix bool members documentation indentation
a26e5f32e0 Gyro degrees per second is 2000 across all 8bitdo controllers (#13147)
fc1c0618de kmsdrm: fixed creating GBM surfaces on NVIDIA cards
03a6d98aee Update SDL_pixels.h
885e611f3c Added macros to push/pop error messages while cleaning up
61d105247e Fixed typos
7db0ac7380 Updated SDL_StretchSurface() documentation
ca988dbc2c Bail out if Xrandr returns zero CRTCs in the X11 messagebox implementation
c147ddf3e3 Do not use Xrandr if the extension is not queryable in the X11 messagebox implementation
df07c09f55 Use visuals and colormapsin the X11 messagebox implementation
737b9e117d Removed obsolete documentation
d2be547642 Removed spurious parentheses
36936cbf37 Set the serial number to the Bluetooth MAC address for 8BitDo controllers
f80e819c5b Sync SDL3 wiki -> header
b7082e7e18 Sync SDL3 wiki -> header
3940c660be begin_code: Added SDL_ALIGNED macro.
aa870d511e Disable SDL_HINT_JOYSTICK_RAWINPUT by default
db972604a8 gpu: Xbox buildfix
8a2e2e75d1 Simplified loop logic
b4f7948410 Ensure that report 06 command reads normally
e3d44cdd51 wayland: Use raw timestamps to calculate the elapsed repeat time on a key up event
b51273512b Sync SDL3 wiki -> header
988c0be934 Sync SDL3 wiki -> header
9b025e3cab PSP fullscreen is the only mode (#13125)
08b6f6175a Sync SDL3 wiki -> header
5e50d39b38 audio: Added SDL_PutAudioStreamDataNoCopy.
25db127450 SDL_video.c: remove two stray line continuation chars .
168d1a9253 emscripten: Proxy Emscripten_GetSystemTheme and EMSCRIPTENAUDIO_OpenDevice to the main thread.
f62572344f Clean up INTERFACE_COMPILE_OPTIONS
b70919ecd9 x11: Assume the window was mapped after showing
0657ece55d x11: Always send fullscreen dimensions except on XWayland
1f6b5c681d Set the initial axis values for HIDAPI and XInput controllers
fdc4f8fa39 x11: Include the XTest header when needed
2b4d61e4a6 VITA: support only fullscreen windows. Fixes #13079
4cd889cb13 joystick: Several minor GIP fixes
0a7548230c Sync SDL3 wiki -> header
c9cf4c42e0 Improved HIDAPI support for Flydigi controllers
ead32c706d fix error handling in WideCharToMultiByte
8ddb074889 bugfix advancing UTF-8 length in UTF-16 string
dcdbc0bf9f README-documentation-rules: Add a note about being UTF-8 only!
56bb73a8d2 README-ngage.md: Really actually got all the non-UTF-8 characters this time!
ecef0d3564 README-ngage.md: Found a few more non-UTF-8 things.
fb7afabbd6 README-ngage.md: Removed non-UTF-8 character.
73ca59b423 Sync SDL3 wiki -> header
136a44b0bd Sync SDL3 wiki -> header
7ae64592c9 Restore support for the Nokia N-Gage (#12148)
26f9940f82 Sync SDL3 wiki -> header
6f994cc7a8 Fixed macOS build
354895d975 Add Flydigi VADER 4 Pro HIDAPI support (#12874)
8d9a4fe843 stdinc: Corrected documentation for SDL_atan2 and SDL_atan2f.
abcfa1b7de wayland: Use SDL_memcpy instead of SDL_copyp to copy the repeated text string
22828d5f2a Fix #13083 segfault in `SDL_RemoveTrayEntry()` for submenu entries
264eb8d440 Fixed the Bluetooth flag for the combined Joy-Con controller
05f779f61e wayland: Cap the max key repeat elapsed time
20e8ac0075 wayland: Fix keymap changed event spam with non-latin keyboard layouts
b8e055ce64 use SDL style - else on same line as closing brace
8e22194217 get preferred locales on android
c08b1049d3 gpu/d3d12: Acknowledge that we've bound vertex buffers (#13088)
c89357bf60 Fix wrong callback type
f4942b3eae GPU: Update D3D12 to create multisample textures with default MSAA alignment
c7549eb0b6 wayland: Set the text input cursor rect properly
3be57ec774 docs: fix man page return value section generation
2dad6534b8 GPU: Add missing compute-writeable texture formats
992e4c59bd Fixed rare crash trying to interrupt SDL_WaitEvent()
4db8fe2f9b Sync SDL3 wiki -> header
6c61a94a4b wayland: Don't add the nanosecond timestamp offset to the pre-conversion millisecond value
25f2376e79 Fixed touch not being delivered as mouse events by default on Vita
afd1e51023 Fix: GameCube controller adapter hotplug not working
510126ee63 gpu: Check shader format support in PrepareDriver
8289656a4e GPU: Update to set supported shader formats inside CreateDevice
514d96de07 Sync SDL3 wiki -> header
d6a99752b7 Fix properties name in SDL_CreateGPUDeviceWithProperties
3dceb728b7 Suppress spammy gamepad and joystick update events
b0a282e31f wayland: Enable relative pointer mode based on the window flag
968222e74f Fix #13057 - fixes bug with NSEventTypeMouseMoved having a NULL window causing us to suppress future mouse move events because the window was considered out of focus.
d16371b923 Fix reference to nonexistent "README-3ds.md"
945eb6dc87 MacOS: fix cocoa clipboard text
b08d79b832 GPU: Check that a texture format is valid for compute writes (#13044)
604c192154 GPU: Always return NULL if beginning a pass fails an assert check
252129f433 GPU: Debug mode layer and level index checks
db154c8b9b Added HIDAPI mapping for the 8BitDo SF30 Pro
ec685e87fd Clarify logic in UpdateLogicalPresentation()
8aa5b97bb5 renderer: Always use the output size when updating the main view
1f7aa16eae wikiheaders: Man pages should escape apostrophe chars.
cf62637261 joystick: Add support for Xbox One Chatpad attachment
83cbf7f811 Sync SDL3 wiki -> header
f85f83ec7c SDL GPU: Implemented opt out Vulkan device features (#13016)
1eeffc5933 Revert "x11: Send key events for dead keys consumed by the IME"
3304d24bea Revert "x11: Filter out duplicate key presses when an IME is active"
cd95152b2c Fixed crash if out of memory in the Vulkan GPU driver
70b2d162e3 audio: Assert that all devices from device_hash are the appropriate type
83d4dce697 wayland: Remove all window references from seats when destroying a window
0a34279578 audio: Fix SDL_GetAudioDeviceName() not working with logical devices.
e2f7c4046c Sync SDL3 wiki -> header
f6c1e81394 [Process API] Quoting enhancements (#12946)
9a6f70d75a tray: Fix wrong `fByPositon` parameter of SetMenuItemInfoW in SDL_SetTrayEntryLabel
38da39c8c9 Added rightx and righty
2ae3418260 GPU Vulkan: set correct destination usage mode for storage buffer read/write bindings (#13009)
c6e9d6cc79 AAudio: Implemented sample frames hint
aaa5d70efc wayland: Check the cursor visibility flag when updating seat pointers
e1066ceea1 Revert "pulseaudio: cleanup TLS every time we finish a threaded-mainloop callback."
84308e7fba x11: Fix the Openbox quirk flag
6344712b04 GPU Vulkan: fix for Swapchain Semaphore Reuse
3f2226a917 Add progress bar support for Linux
e90f7ac4a8 Add hid_version and hid_version_str to renamed LIBUSB impl symbols
f92843da83 Sync SDL3 wiki -> header
86b206dadf GPU: Special case to avoid assert on GenerateMipmaps (#12995)
7b3bd8c538 joystick: Improve GIP metadata retry
367cf9ba63 joystick: Always continue processing GIP packets
955a49c883 joystick: Add quirk for no impulse vibration on the Spectra Pro
82899501b5 joystick: Fix GIP fast ACK issue
9e0edea16f joystick: Assume GIP gamepads have the LED command if no metadata is present
9a96960728 joystick: Sort out GIP vendor messages into the supported interfaces
72dd79752e joystick: Add initial support for GIP flight sticks
2248d3812e joystick: Rework GIP code to allow separate states for individual attachments
87fe9ef79b Fixed crash if WGI isn't correlated in RAWINPUT_JoystickRumble()
29d2116495 Define illegal_instruction() when it will be actually used
2aa0957081 Fixed 8BitDo Ultimate 2 Wireless controller on macOS
ad55597715 ci: Update Steam Linux Runtime tasks.
36c3a7a5e2 ci: Add slrsniper-arm64 task
8690a9ab54 Prefer the HIDAPI driver for 8BitDo controllers on macOS
2b57d58f7d Added GCController mapping for the 8BitDo SN30 Pro on macOS
d157600d3d Added GCController mapping for the 8BitDo Pro 2 on macOS
09c8d4b556 Sync SDL3 wiki -> header
37b86a6d2f windows: fix Unicode function and type inconsistencies
d9e58baa6d fixed the  field of SDL_MouseMotionTransformCallback
e7a765d648 Replace SDL_free with delete for new-allocated objects
5bee85408c Cleanup 8BitDo HIDAPI support for SF30 Pro and SN30 Pro
89a8cf2505 Sync SDL3 wiki -> header
6b048f59d7 fix #12963
2b3c481215 add 8BitDo Controller (#12964)
ca47dc59a9 Fixed building with the OpenVR video driver
195ad85ba4 Fixed typo
f4813ca2cf x11: Filter out duplicate key presses when an IME is active
8e1f4bafb4 [emscripten] Remove referenc to Module['createContext']
1dbb813316 VITA: fix audio playback
20f783532b Sync SDL3 wiki -> header
bbd973c8d2 Sync SDL3 wiki -> header
71303b41bf Sync SDL3 wiki -> header
a7344206e8 wikiheaders: Patched to compile.
06c2f9fcfc wikiheaders: Correct wiki README digest links.
ad46394e82 wikiheaders: README.md should be READMEs.md
2c97a48c51 wikiheaders: READMEs go in the base dir of the wiki now.
92a5417a98 docs: Tweak some minor things to keep wikiheaders happy.
d357aa29a3 Fixed initializing the OpenVR driver
f8c77908ad Use motor sequence ID 0 in the HIDAPI GIP driver
33e5f4885a x11: Don't update grab on enter when the mouse is captured
1abac3ccc3 Revert "x11: Better handle XInput2 mouse tracking outside the window"
85d2345bd8 Sync SDL3 wiki -> header
5bd886519b Sync SDL3 wiki -> header
c6362b4788 tests: Revert some leftover testing code
c91f9f6968 x11: #ifdef the XRandR path in the message box code
7490471796 cpuinfo: Use auxv for AltiVec on Linux if possible
17bba029ba don't prototype strdup() for __clang_analyzer__ case in windows builds.
15c6acf74f capture g27 shifter r input
795d1ae1fb testmessage: Don't push the event if "Retry" was chosen.
d73fe0bc53 win32: Hide the borders when showing a fullscreen window
ab12b7cbba Added support for the share button on the GameSir-K1 FLUX controller
1e6a25324c Added support for the PowerA Battle Dragon Advanced Wireless Controller
57346f2ba8 dialog: Cocoa backend should reactivate the app after the modal dialog.
caf269ce00 Added a link to the GIP documentation
34c045aa39 Fixed paddles on the Xbox Elite controller using the GIP driver
0447c2f3c3 events: Add integer wheel fields for sdl2-compat
ae251a05be Fixed warning: no previous prototype for function 'GIP_ParseMetadata'
193b0c8963 uikit: Use SDL_RunOnMainThread instead of dispatch_sync for message boxes.
691cc5bb5e dialog: Cocoa shouldn't crash if there's a '.' in the filters.
4ef8b6ce1b X11: Center Message Box on Multi Monitor Displays (#12819)
c5d5967c3a video: Store the preferred fullscreen display in a property for sdl2-compat
11e1d4a145 Sync SDL3 wiki -> header
00f3a82ada Joystick: Add new GIP driver to replace old Xbox One wired driver
48dfc03a87 Added the gamepad hint SDL_GAMECONTROLLER_USE_GAMECUBE_LABELS
21a7bbbf14 Restore compatibility with older GameCube mappings
3730128e33 Simplify WIN_CreateHCursor (#12933)
6a0505c090 wayland: Remove unnecessary function call
fdd8b5d630 wayland: Query the mouse global button states from the seats
e3df61b070 Fixed right mouse button emulation when using a pen
106ccc722e Fixed missing simulated mouse events using a Wacom tablet
8ae962c904 Fixed build
e04064350f Fixed right click mouse emulation for the Wacom tablet
a163257295 GPU: Validate that textures are not bound for both read and write on render passes (#12925)
ea67133e4f pen: Windows can't check WM_POINTER[DOWN|UP] for touches directly.
f131791005 Sync SDL3 wiki -> header
e1a41c1c97 GPU Vulkan: Add locks for layout object lookups (#12924)
fd5380ffc6 Sync SDL3 wiki -> header
b871ac0d97 Add support for non-constrained and non-grabbing popups
8abcc27535 Removed timeout in SDL_RunOnMainThread()
ef54c3bf18 Always enable D3D12 GPU on Windows
39d3148185 events: Fix undefined behavior when disabling some event types
510c7edd9b migrate usage of SetCursor(NULL) to RedrawCursor()
4779499048 Split the redraw effect to own function
6c172e5220 SDL_SetCursor should not skip focus check
cbf44700d8 bytepusher example: always render text to render target and remove unused variable
faddff1bcc Sync SDL3 wiki -> header
31650d566c Added SDL_GAMEPAD_TYPE_GAMECUBE
c4d5cc358f streamline boolean logic
441e7e488f invert cursor_visible to hide_cursor
d553372682 rename cursor_shown to cursor_visible
016ba86f93 tray, unix: make pointers g_object_ref and g_object_ref_sink static
6f5892e543 cocoa: Immediately update the mouse focus when showing/hiding a popup menu
8c733d1f7b x11: Better handle XInput2 mouse tracking outside the window
0dbf585ace fix SDL_audiocvt.c MSVC build.
af0972c33f audio: SDL_PutAudioStreamPlanarData should take a channel count.
5f03cb3882 d3d12: Patched to compile with GDK builds.
360cc2791f test/msdf_font.bmp: mark as non-executable.
34fe967f3e Sync SDL3 wiki -> header
22692e308f events: Added SDL_GetEventDescription().
c2ed58db7b windows: Fix stale zoom/iconic state in WM_WINDOWPOSCHANGED handler
14ae45c2b8 GDK: Handle ProjectDir with space
faa2e40406 gpu: Warn about Direct3D 12 texture alignment requirements.
2e45198299 Sync SDL3 wiki -> header
608f706a95 audio: Added SDL_SetAudioIterationCallbacks().
18a86ea6bb testaudio: Use SDL_SetAppMetadata at startup.
a9bee3c0bf pipewire: Use a more specific stream name than "Audio Stream".
2767c1a440 aaudio: We PlayDevice first and WaitDevice after; reduce semaphore count by 1.
7642c0468d Log information about Wayland environment detection
5b1e92ae88 cmake: use CMAKE_ANDROID_NDK variable as root of Android ndk
09b2aae47e cocoa: Popup menus always accept first click
29ef31d589 Sync SDL3 wiki -> header
15cb9bd610 Sync SDL3 wiki -> header
b28449a58c audio: Tweak SDL_GetAudioDeviceName.
da3c864d4c Reset the keyboard when entering a modal loop on Windows
a82f70dc21 use GetMessagePos instead of GetCursorPos
bfbeaca29f inline WIN_UpdateMouseCapture
de2c5c33b7 SDL_hidapi_steamdeck: report touch controller events
5cacdf2513 Fix crash in UIKit indirect pointer handling
32bbabe2a5 Add Padix Rockfire devices (#12884)
7e1d4f843c Emscripten: fix incorrect error check for WebGL context creation
fcdaff4110 Fixed compiler warning
dd625a6763 defer clipcursor refresh unto pump finish
c84c2aa2c4 pass ground-truth cursor pos to WIN_UpdateFocus
11a3296a42 x11: Handle size/position events arriving before state events
d50520462a Add and use SDL_HapticEffectID typedef
fb940fff80 audio: Fix warning C4701: potentially uninitialized local variable 'isstack' used
e8bd9cc150 audio: SDL_GetAudioDeviceName() doesn't need a full device lock.
3343cb2147 gpu: rework alpha-to-coverage validation
ceb9fecfc1 Joystick: Add trigger rumble resend
c81b62293a GPU D3D12 - Update to use typeless formats for depth buffer (#12701)
27b256022b SDL_GetRectIntersectionFloat(): Allow rendering zero-sized srcrect
d04b28926c GPU: Make D3D12 debug layers optional
695cad459b Corrected documentation for SDL_SetGPUSwapchainParameters()
2b16c961ea Add and use typedefs SDL_HapticEffectType and SDL_HapticDirectionType
a1332d77f6 wayland: Cleanup timestamp handling
b5ed0d0138 stb_image.h: apply mainstream PR/1736
e3181a0bcd Sync SDL3 wiki -> header
e3507b390e examples: added audio/05-planar-data
3905aa0587 audio: Added SDL_PutAudioStreamPlanarData.
483d1c36ed comments: Fixed a few typos I ran into in the audio code.
727a5fae59 Sync SDL3 wiki -> header
5a8be8e4c2 Fixed formatting
6e4ace310c GPU: Validate shader bytecode
89d7d406ab Added tests to cover invalid surface blits
fe849f1572 SDL_BlitSurfaceScaled(): Do not divide by zero
8017d38adc SDL_BlitSurfaceScaled(): Do not blit if surfaces have no pixel data
18fbe6a92f Renamed SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 to SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER
6a6917b0df Sync SDL3 wiki -> header
e70a49892b Add missing type suffix to SDL_PROP_WINDOW_OPENVR_OVERLAY_ID
a696b108ac SDL_BlitSurface() comment: Remove sentence about final blit rect being stored in srcrect and dstrect
c076b0d17f Removed incorrect documentation for SDL_RenderViewportSet()
47162a4168 x11: Send key events for dead keys consumed by the IME
3aed80cd82 Updated documentation for SDL_HINT_GPU_DRIVER
86b3369491 wayland: Check the origin of clipboard offers before forwarding them to the client
23a7a74133 Sync SDL3 wiki -> header
3be0ec5631 Sync SDL3 wiki -> header
5bd1578a45 wayland: Account for timer rollover when calculating the elapsed time for key repeats.
10f51da28d cocoa: Use CGFLOAT_MAX for unbounded max window dimensions
3519a59d8f The SDL_BUTTON_*MASK defines must come immediately after the SDL_MouseButtonFlags typedef to be associated
8e0b39f465 Sync SDL3 wiki -> header
9da46bc37f win32: Check internal data when positioning child windows

git-subtree-dir: external/SDL
git-subtree-split: 279dabfc96631965f8dad2e39d57daa4b9130d24
This commit is contained in:
irisz64
2025-06-26 22:23:47 +02:00
parent 28d94e8b86
commit b22c6238d5
317 changed files with 18074 additions and 2718 deletions

View File

@@ -0,0 +1,102 @@
name: 'Setup Nonka N-Gage SDK'
description: 'Download and setup Nokia N-Gage SDK'
inputs:
path:
description: 'Installation path'
default: 'default'
runs:
using: 'composite'
steps:
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: 'Verify platform'
id: calc
shell: sh
run: |
case "${{ runner.os }}-${{ runner.arch }}" in
"Windows-X86" | "Windows-X64")
echo "ok!"
echo "cache-key=ngage-sdk-windows" >> ${GITHUB_OUTPUT}
default_install_path="C:/ngagesdk"
;;
*)
echo "Unsupported ${{ runner.os }}-${{ runner.arch }}"
exit 1;
;;
esac
install_path="${{ inputs.path }}"
if [ "x$install_path" = "xdefault" ]; then
install_path="$default_install_path"
fi
echo "install-path=$install_path" >> ${GITHUB_OUTPUT}
toolchain_repo="https://github.com/ngagesdk/ngage-toolchain"
toolchain_branch="main"
echo "toolchain-repo=${toolchain_repo}" >> ${GITHUB_OUTPUT}
echo "toolchain-branch=${toolchain_branch}" >> ${GITHUB_OUTPUT}
sdk_repo="https://github.com/ngagesdk/sdk"
sdk_branch="main"
echo "sdk-repo=${sdk_repo}" >> ${GITHUB_OUTPUT}
echo "sdk-branch=${sdk_branch}" >> ${GITHUB_OUTPUT}
tools_repo="https://github.com/ngagesdk/tools"
tools_branch="main"
echo "tools-repo=${tools_repo}" >> ${GITHUB_OUTPUT}
echo "tools-branch=${tools_branch}" >> ${GITHUB_OUTPUT}
extras_repo="https://github.com/ngagesdk/extras"
extras_branch="main"
echo "extras-repo=${extras_repo}" >> ${GITHUB_OUTPUT}
echo "extras-branch=${extras_branch}" >> ${GITHUB_OUTPUT}
# - name: 'Restore cached ${{ steps.calc.outputs.archive }}'
# id: cache-restore
# uses: actions/cache/restore@v4
# with:
# path: '${{ runner.temp }}'
# key: ${{ steps.calc.outputs.cache-key }}
- name: 'Download N-Gage SDK'
# if: ${{ !steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false' }}
shell: pwsh
run: |
Invoke-WebRequest "${{ steps.calc.outputs.toolchain-repo }}/archive/refs/heads/${{ steps.calc.outputs.toolchain-branch }}.zip" -OutFile "${{ runner.temp }}/ngage-toolchain.zip"
Invoke-WebRequest "${{ steps.calc.outputs.sdk-repo }}/archive/refs/heads/${{ steps.calc.outputs.sdk-branch }}.zip" -OutFile "${{ runner.temp }}/sdk.zip"
Invoke-WebRequest "${{ steps.calc.outputs.tools-repo }}/archive/refs/heads/${{ steps.calc.outputs.tools-branch }}.zip" -OutFile "${{ runner.temp }}/tools.zip"
Invoke-WebRequest "${{ steps.calc.outputs.extras-repo }}/archive/refs/heads/${{ steps.calc.outputs.extras-branch }}.zip" -OutFile "${{ runner.temp }}/extras.zip"
# - name: 'Cache ${{ steps.calc.outputs.archive }}'
# if: ${{ !steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false' }}
# uses: actions/cache/save@v4
# with:
# path: |
# ${{ runner.temp }}/apps.zip
# ${{ runner.temp }}/sdk.zip
# ${{ runner.temp }}/tools.zip
# key: ${{ steps.calc.outputs.cache-key }}
- name: 'Extract N-Gage SDK'
shell: pwsh
run: |
New-Item -ItemType Directory -Path "${{ steps.calc.outputs.install-path }}" -Force
New-Item -ItemType Directory -Path "${{ runner.temp }}/ngage-toolchain-temp" -Force
7z "-o${{ runner.temp }}/ngage-toolchain-temp" x "${{ runner.temp }}/ngage-toolchain.zip"
Move-Item -Path "${{ runner.temp }}/ngage-toolchain-temp/ngage-toolchain-${{ steps.calc.outputs.toolchain-branch }}/*" -Destination "${{ steps.calc.outputs.install-path }}"
7z "-o${{ steps.calc.outputs.install-path }}/sdk" x "${{ runner.temp }}/sdk.zip"
Move-Item -Path "${{ steps.calc.outputs.install-path }}/sdk/sdk-${{ steps.calc.outputs.sdk-branch }}" -Destination "${{ steps.calc.outputs.install-path }}/sdk/sdk"
7z "-o${{ steps.calc.outputs.install-path }}/sdk" x "${{ runner.temp }}/tools.zip"
Move-Item -Path "${{ steps.calc.outputs.install-path }}/sdk/tools-${{ steps.calc.outputs.tools-branch }}" -Destination "${{ steps.calc.outputs.install-path }}/sdk/tools"
7z "-o${{ steps.calc.outputs.install-path }}/sdk" x "${{ runner.temp }}/extras.zip"
Move-Item -Path "${{ steps.calc.outputs.install-path }}/sdk/extras-${{ steps.calc.outputs.extras-branch }}" -Destination "${{ steps.calc.outputs.install-path }}/sdk/extras"
- name: 'Set output variables'
id: final
shell: sh
run: |
echo "${{ steps.calc.outputs.install-path }}/sdk/sdk/6.1/Shared/EPOC32/gcc/bin" >> $GITHUB_PATH
echo "${{ steps.calc.outputs.install-path }}/sdk/sdk/6.1/Shared/EPOC32/ngagesdk/bin" >> $GITHUB_PATH
echo "NGAGESDK=${{ steps.calc.outputs.install-path }}" >> $GITHUB_ENV
echo "CMAKE_TOOLCHAIN_FILE=${{ steps.calc.outputs.install-path }}/cmake/ngage-toolchain.cmake" >> $GITHUB_ENV

View File

@@ -54,6 +54,7 @@ class SdlPlatform(Enum):
Riscos = "riscos"
FreeBSD = "freebsd"
NetBSD = "netbsd"
NGage = "ngage"
class Msys2Platform(Enum):
@@ -113,7 +114,8 @@ JOB_SPECS = {
"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-22.04": JobSpec(name="Ubuntu 22.04", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04", ),
"ubuntu-24.04-arm64": JobSpec(name="Ubuntu 24.04 (ARM64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-ubuntu24.04-arm64", ),
"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", ),
"steamrt3": JobSpec(name="Steam Linux Runtime 3.0 (x86_64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-steamrt3", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest", ),
"steamrt3-arm64": JobSpec(name="Steam Linux Runtime 3.0 (arm64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-steamrt3-arm64", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk/arm64:latest", ),
"ubuntu-intel-icx": JobSpec(name="Ubuntu 22.04 (Intel oneAPI)", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04-oneapi", intel=IntelCompiler.Icx, ),
"ubuntu-intel-icc": JobSpec(name="Ubuntu 22.04 (Intel Compiler)", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04-icc", intel=IntelCompiler.Icc, ),
"macos-framework-x64": JobSpec(name="MacOS (Framework) (x64)", os=JobOs.Macos13, platform=SdlPlatform.MacOS, artifact="SDL-macos-framework", apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, xcode=True, ),
@@ -138,11 +140,12 @@ JOB_SPECS = {
"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", ),
"freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ),
"ngage": JobSpec(name="N-Gage", os=JobOs.WindowsLatest, platform=SdlPlatform.NGage, artifact="SDL-ngage", ),
}
class StaticLibType(Enum):
MSVC = "SDL3-static.lib"
STATIC_LIB = "SDL3-static.lib"
A = "libSDL3.a"
@@ -222,6 +225,7 @@ class JobDetails:
check_sources: bool = False
setup_python: bool = False
pypi_packages: list[str] = dataclasses.field(default_factory=list)
setup_gage_sdk_path: str = ""
def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
data = {
@@ -289,6 +293,7 @@ class JobDetails:
"check-sources": self.check_sources,
"setup-python": self.setup_python,
"pypi-packages": my_shlex_join(self.pypi_packages),
"setup-ngage-sdk-path": self.setup_gage_sdk_path,
}
return {k: v for k, v in data.items() if v != ""}
@@ -364,7 +369,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
job.msvc_project_flags.append("-p:TreatWarningsAsError=true")
job.test_pkg_config = False
job.shared_lib = SharedLibType.WIN32
job.static_lib = StaticLibType.MSVC
job.static_lib = StaticLibType.STATIC_LIB
job.cmake_arguments.extend((
"-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase",
"-DCMAKE_EXE_LINKER_FLAGS=-DEBUG",
@@ -739,6 +744,19 @@ 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.NGage:
build_parallel = False
job.cmake_build_type = "Release"
job.setup_ninja = True
job.static_lib = StaticLibType.STATIC_LIB
job.shared_lib = None
job.clang_tidy = False
job.werror = False # FIXME: enable SDL_WERROR
job.shared = False
job.run_tests = False
job.setup_gage_sdk_path = "C:/ngagesdk"
job.cmake_toolchain_file = "C:/ngagesdk/cmake/ngage-toolchain.cmake"
job.test_pkg_config = False
case _:
raise ValueError(f"Unsupported platform={spec.platform}")

View File

@@ -93,6 +93,11 @@ jobs:
with:
arch: ${{ matrix.platform.msvc-vcvars-arch }}
sdk: ${{ matrix.platform.msvc-vcvars-sdk }}
- name: 'Set up Nokia N-Gage SDK'
uses: ./.github/actions/setup-ngage-sdk
if: ${{ matrix.platform.setup-ngage-sdk-path != '' }}
with:
path: '${{ matrix.platform.setup-ngage-sdk-path }}'
- name: 'Set up Windows GDK Desktop'
uses: ./.github/actions/setup-gdk-desktop
if: ${{ matrix.platform.setup-gdk-folder != '' }}

View File

@@ -9,6 +9,7 @@ versionfname = include/SDL3/SDL_version.h
versionmajorregex = \A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z
versionminorregex = \A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z
versionmicroregex = \A\#define\s+SDL_MICRO_VERSION\s+(\d+)\Z
apipropertyregex = \A\s*\#\s*define\s+SDL_PROP_
selectheaderregex = \ASDL.*?\.h\Z
projecturl = https://libsdl.org/
wikiurl = https://wiki.libsdl.org
@@ -25,7 +26,7 @@ manpagesymbolfilterregex = \A[US]int\d+\Z
headercategoryeval = s/\ASDL_test_?.*?\.h\Z//; s/\ASDL_?(.*?)\.h\Z/$1/; ucfirst();
quickrefenabled = 1
quickrefcategoryorder = Init,Hints,Error,Version,Properties,Log,Video,Events,Keyboard,Mouse,Touch,Gamepad,Joystick,Haptic,Audio,Time,Timer,Render,SharedObject,Thread,Mutex,Atomic,Filesystem,IOStream,AsyncIO,Storage,Pixels,Surface,Blendmode,Rect,Camera,Clipboard,Dialog,GPU,Messagebox,Vulkan,Metal,Platform,Power,Sensor,Process,Bits,Endian,Assert,CPUInfo,Intrinsics,Locale,System,Misc,GUID,Main,Stdinc
quickrefcategoryorder = Init,Hints,Error,Version,Properties,Log,Video,Events,Keyboard,Mouse,Touch,Gamepad,Joystick,Haptic,Audio,Time,Timer,Render,SharedObject,Thread,Mutex,Atomic,Filesystem,IOStream,AsyncIO,Storage,Pixels,Surface,Blendmode,Rect,Camera,Clipboard,Dialog,Tray,Messagebox,GPU,Vulkan,Metal,Platform,Power,Sensor,Process,Bits,Endian,Assert,CPUInfo,Intrinsics,Locale,System,Misc,GUID,Main,Stdinc
quickreftitle = SDL3 API Quick Reference
quickrefurl = https://libsdl.org/
quickrefdesc = The latest version of this document can be found at https://wiki.libsdl.org/SDL3/QuickReference

View File

@@ -76,6 +76,7 @@ include("${SDL3_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake")
include("${SDL3_SOURCE_DIR}/cmake/3rdparty.cmake")
include("${SDL3_SOURCE_DIR}/cmake/PreseedMSVCCache.cmake")
include("${SDL3_SOURCE_DIR}/cmake/PreseedEmscriptenCache.cmake")
include("${SDL3_SOURCE_DIR}/cmake/PreseedNokiaNGageCache.cmake")
SDL_DetectCompiler()
SDL_DetectTargetCPUArchitectures(SDL_CPUS)
@@ -155,7 +156,7 @@ endif()
# The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers,
# so we'll just use libusb when it's available. libusb does not support iOS,
# so we default to yes on iOS.
if(IOS OR TVOS OR VISIONOS OR WATCHOS OR ANDROID)
if(IOS OR TVOS OR VISIONOS OR WATCHOS OR ANDROID OR NGAGE)
set(SDL_HIDAPI_LIBUSB_AVAILABLE FALSE)
else()
set(SDL_HIDAPI_LIBUSB_AVAILABLE TRUE)
@@ -219,7 +220,7 @@ if(EMSCRIPTEN)
set(SDL_SHARED_AVAILABLE OFF)
endif()
if(VITA OR PSP OR PS2 OR N3DS OR RISCOS)
if(VITA OR PSP OR PS2 OR N3DS OR RISCOS OR NGAGE)
set(SDL_SHARED_AVAILABLE OFF)
endif()
@@ -414,6 +415,24 @@ if(VITA)
set_option(VIDEO_VITA_PVR "Build with PSVita PVR gles/gles2 support" OFF)
endif()
if (NGAGE)
set(SDL_GPU OFF)
set(SDL_CAMERA OFF)
set(SDL_JOYSTICK OFF)
set(SDL_HAPTIC OFF)
set(SDL_HIDAPI OFF)
set(SDL_POWER OFF)
set(SDL_SENSOR OFF)
set(SDL_DIALOG OFF)
set(SDL_DISKAUDIO OFF)
set(SDL_DUMMYAUDIO OFF)
set(SDL_DUMMYCAMERA OFF)
set(SDL_DUMMYVIDEO OFF)
set(SDL_OFFSCREEN OFF)
set(SDL_RENDER_GPU OFF)
set(SDL_VIRTUAL_JOYSTICK OFF)
endif()
if(NOT (SDL_SHARED OR SDL_STATIC))
message(FATAL_ERROR "SDL_SHARED and SDL_STATIC cannot both be disabled")
endif()
@@ -1294,8 +1313,8 @@ if(ANDROID)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/android")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/android/*.c")
sdl_sources("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_property(SOURCE "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
sdl_sources("${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_property(SOURCE "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/android/*.c")
set(HAVE_SDL_MISC TRUE)
@@ -1736,6 +1755,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
sdl_sources(
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_dbus.c"
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_system_theme.c"
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_progressbar.c"
)
endif()
@@ -2930,6 +2950,81 @@ elseif(N3DS)
set(HAVE_SDL_LOCALE TRUE)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/io/n3ds/*.c")
elseif(NGAGE)
enable_language(CXX)
set(SDL_MAIN_USE_CALLBACKS 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/ngage/*.c")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/ngage/*.cpp")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/ngage/*.cpp")
set(HAVE_SDL_MAIN_CALLBACKS TRUE)
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_NGAGE 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/ngage/*.c")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/ngage/*.cpp")
set(HAVE_SDL_AUDIO TRUE)
endif()
set(SDL_FILESYSTEM_NGAGE 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/ngage/*.c")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/ngage/*.cpp")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/ngage/*.cpp")
if(SDL_RENDER)
set(SDL_VIDEO_RENDER_NGAGE 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/render/ngage/*.c")
endif()
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/ngage/*.cpp")
set(SDL_TIME_NGAGE 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/render/ngage/*.cpp")
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
set(SDL_TIMER_NGAGE 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/ngage/*.cpp")
set(SDL_FSOPS_POSIX 1)
set(SDL_VIDEO_DRIVER_NGAGE 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/ngage/*.c")
set(HAVE_SDL_TIMERS TRUE)
set_option(SDL_LEAN_AND_MEAN "Enable lean and mean" ON)
if(SDL_LEAN_AND_MEAN)
sdl_compile_definitions(
PRIVATE
SDL_LEAN_AND_MEAN
)
endif()
sdl_link_dependency(ngage
LINK_OPTIONS "SHELL:-s MAIN_COMPAT=0"
PKG_CONFIG_LINK_OPTIONS "-s;MAIN_COMPAT=0"
LIBS
NRenderer
3dtypes
cone
libgcc
libgcc_ngage
mediaclientaudiostream
charconv
bitgdi
euser
estlib
ws32
hal
fbscli
efsrv
scdv
gdi
)
endif()
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog.c)
@@ -3023,7 +3118,7 @@ if(SDL_GPU)
set(SDL_GPU_D3D11 1)
set(HAVE_SDL_GPU TRUE)
endif()
if(SDL_RENDER_D3D12)
if(WINDOWS)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d12/*.c")
set(SDL_GPU_D3D12 1)
set(HAVE_SDL_GPU TRUE)
@@ -3110,8 +3205,8 @@ endif()
# We always need to have threads and timers around
if(NOT HAVE_SDL_THREADS)
# The emscripten platform has been carefully vetted to work without threads
if(EMSCRIPTEN)
# The Emscripten and N-Gage platform has been carefully vetted to work without threads
if(EMSCRIPTEN OR NGAGE)
set(SDL_THREADS_DISABLED 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/thread/generic/*.c")
else()
@@ -3294,7 +3389,7 @@ else()
endif()
if(ANDROID)
sdl_include_directories(PRIVATE SYSTEM "${ANDROID_NDK}/sources/android/cpufeatures")
sdl_include_directories(PRIVATE SYSTEM "${CMAKE_ANDROID_NDK}/sources/android/cpufeatures")
endif()
if(APPLE)

View File

@@ -168,8 +168,8 @@
</Link>
<PreBuildEvent>
<Command>
call $(ProjectDir)..\..\src\render\direct3d12\compile_shaders_xbox.bat $(ProjectDir)..\
call $(ProjectDir)..\..\src\gpu\d3d12\compile_shaders_xbox.bat $(ProjectDir)..\
call "$(ProjectDir)..\..\src\render\direct3d12\compile_shaders_xbox.bat" "$(ProjectDir)..\"
call "$(ProjectDir)..\..\src\gpu\d3d12\compile_shaders_xbox.bat" "$(ProjectDir)..\"
</Command>
</PreBuildEvent>
<PreBuildEvent>
@@ -713,8 +713,10 @@
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.cpp" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_8bitdo.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_flydigi.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gip.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps3.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />

View File

@@ -64,8 +64,10 @@
<ClCompile Include="..\..\src\joystick\gdk\SDL_gameinputjoystick.cpp" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_8bitdo.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_flydigi.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gip.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps3.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />

View File

@@ -603,8 +603,10 @@
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_8bitdo.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_flydigi.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gip.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps3.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />

View File

@@ -1185,12 +1185,18 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_8bitdo.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_flydigi.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gip.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>

View File

@@ -438,6 +438,7 @@
F3B439532C935C2C00792030 /* SDL_posixprocess.c in Sources */ = {isa = PBXBuildFile; fileRef = F3B439522C935C2C00792030 /* SDL_posixprocess.c */; };
F3B439562C937DAB00792030 /* SDL_process.c in Sources */ = {isa = PBXBuildFile; fileRef = F3B439542C937DAB00792030 /* SDL_process.c */; };
F3B439572C937DAB00792030 /* SDL_sysprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B439552C937DAB00792030 /* SDL_sysprocess.h */; };
F3B6B80A2DC3EA54004954FD /* SDL_hidapi_gip.c in Sources */ = {isa = PBXBuildFile; fileRef = F3B6B8092DC3EA54004954FD /* SDL_hidapi_gip.c */; };
F3C1BD752D1F1A3000846529 /* SDL_tray_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = F3C1BD742D1F1A3000846529 /* SDL_tray_utils.c */; };
F3C1BD762D1F1A3000846529 /* SDL_tray_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F3C1BD732D1F1A3000846529 /* SDL_tray_utils.h */; };
F3C2CB222C5DDDB2004D7998 /* SDL_categories_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */; };
@@ -540,6 +541,7 @@
F3FA5A232B59ACE000FEAD97 /* yuv_rgb_lsx.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FA5A1A2B59ACE000FEAD97 /* yuv_rgb_lsx.c */; };
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */; };
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */; };
F3FBB1082DDF93AB0000F99F /* SDL_hidapi_flydigi.c in Sources */ = {isa = PBXBuildFile; fileRef = F3395BA72D9A5971007246C9 /* SDL_hidapi_flydigi.c */; };
F3FD042E2C9B755700824C4C /* SDL_hidapi_nintendo.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */; };
F3FD042F2C9B755700824C4C /* SDL_hidapi_steam_hori.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */; };
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); settings = {ATTRIBUTES = (Required, ); }; };
@@ -948,6 +950,7 @@
F338A1172D1B37D8007CDFDF /* SDL_tray.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDL_tray.m; sourceTree = "<group>"; };
F338A1192D1B37E4007CDFDF /* SDL_tray.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_tray.c; sourceTree = "<group>"; };
F3395BA72D9A5971007246C8 /* SDL_hidapi_8bitdo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_8bitdo.c; sourceTree = "<group>"; };
F3395BA72D9A5971007246C9 /* SDL_hidapi_flydigi.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_flydigi.c; sourceTree = "<group>"; };
F344003C2D4022E1003F26D7 /* INSTALL.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = INSTALL.md; sourceTree = "<group>"; };
F362B9152B3349E200D30B94 /* controller_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_list.h; sourceTree = "<group>"; };
F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamepad_c.h; sourceTree = "<group>"; };
@@ -1012,6 +1015,7 @@
F3B439522C935C2C00792030 /* SDL_posixprocess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_posixprocess.c; sourceTree = "<group>"; };
F3B439542C937DAB00792030 /* SDL_process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_process.c; sourceTree = "<group>"; };
F3B439552C937DAB00792030 /* SDL_sysprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysprocess.h; sourceTree = "<group>"; };
F3B6B8092DC3EA54004954FD /* SDL_hidapi_gip.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_gip.c; sourceTree = "<group>"; };
F3C1BD732D1F1A3000846529 /* SDL_tray_utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_tray_utils.h; sourceTree = "<group>"; };
F3C1BD742D1F1A3000846529 /* SDL_tray_utils.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_tray_utils.c; sourceTree = "<group>"; };
F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_categories_c.h; sourceTree = "<group>"; };
@@ -1927,7 +1931,9 @@
children = (
F3395BA72D9A5971007246C8 /* SDL_hidapi_8bitdo.c */,
F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */,
F3395BA72D9A5971007246C9 /* SDL_hidapi_flydigi.c */,
A7D8A7C923E2513E00DCD162 /* SDL_hidapi_gamecube.c */,
F3B6B8092DC3EA54004954FD /* SDL_hidapi_gip.c */,
89E5801D2D03602200DAF6D3 /* SDL_hidapi_lg4ff.c */,
F3F07D59269640160074468B /* SDL_hidapi_luna.c */,
F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */,
@@ -3056,6 +3062,7 @@
A7D8BA5B23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */,
A7D8B14023E2514200DCD162 /* SDL_blit_1.c in Sources */,
A7D8BBDB23E2574800DCD162 /* SDL_uikitmetalview.m in Sources */,
F3B6B80A2DC3EA54004954FD /* SDL_hidapi_gip.c in Sources */,
A7D8BB1523E2514500DCD162 /* SDL_mouse.c in Sources */,
F395C19C2569C68F00942BFF /* SDL_iokitjoystick.c in Sources */,
A7D8B4B223E2514300DCD162 /* SDL_sysjoystick.c in Sources */,
@@ -3082,6 +3089,7 @@
00001B2471F503DD3C1B0000 /* SDL_camera_dummy.c in Sources */,
00002B20A48E055EB0350000 /* SDL_camera_coremedia.m in Sources */,
000080903BC03006F24E0000 /* SDL_filesystem.c in Sources */,
F3FBB1082DDF93AB0000F99F /* SDL_hidapi_flydigi.c in Sources */,
0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */,
0000494CC93F3E624D3C0000 /* SDL_systime.c in Sources */,
000095FA1BDE436CF3AF0000 /* SDL_time.c in Sources */,

View File

@@ -92,7 +92,7 @@ if(NOT TARGET SDL3::Headers)
add_library(SDL3::Headers INTERFACE IMPORTED)
set_target_properties(SDL3::Headers
PROPERTIES
INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${_sdl3_framework_parent_path}\""
INTERFACE_COMPILE_OPTIONS "-F${_sdl3_framework_parent_path}"
)
endif()
set(SDL3_Headers_FOUND TRUE)

View File

@@ -50,6 +50,8 @@
boolean supportsRelativeMouse();
int openFileDescriptor(java.lang.String, java.lang.String);
boolean showFileDialog(java.lang.String[], boolean, boolean, int);
java.lang.String getPreferredLocales();
java.lang.String formatLocale(java.util.Locale);
}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {

View File

@@ -288,9 +288,13 @@ public class HIDDeviceManager {
0x1532, // Razer Wildcat
0x20d6, // PowerA
0x24c6, // PowerA
0x294b, // Snakebyte
0x2dc8, // 8BitDo
0x2e24, // Hyperkin
0x2e95, // SCUF
0x3285, // Nacon
0x3537, // GameSir
0x366c, // ByoWave
};
if (usbInterface.getId() == 0 &&

View File

@@ -23,6 +23,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.LocaleList;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.DisplayMetrics;
@@ -2116,6 +2117,44 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
int requestCode;
boolean multipleChoice;
}
/**
* This method is called by SDL using JNI.
*/
public static String getPreferredLocales() {
String result = "";
if (Build.VERSION.SDK_INT >= 24 /* Android 7 (N) */) {
LocaleList locales = LocaleList.getAdjustedDefault();
for (int i = 0; i < locales.size(); i++) {
if (i != 0) result += ",";
result += formatLocale(locales.get(i));
}
} else if (mCurrentLocale != null) {
result = formatLocale(mCurrentLocale);
}
return result;
}
public static String formatLocale(Locale locale) {
String result = "";
String lang = "";
if (locale.getLanguage() == "in") {
// Indonesian is "id" according to ISO 639.2, but on Android is "in" because of Java backwards compatibility
lang = "id";
} else if (locale.getLanguage() == "") {
// Make sure language is never empty
lang = "und";
} else {
lang = locale.getLanguage();
}
if (locale.getCountry() == "") {
result = lang;
} else {
result = lang + "_" + locale.getCountry();
}
return result;
}
}
/**

View File

@@ -32,6 +32,7 @@ my $wikisubdir = '';
my $incsubdir = 'include';
my $readmesubdir = undef;
my $apiprefixregex = undef;
my $apipropertyregex = undef;
my $versionfname = 'include/SDL_version.h';
my $versionmajorregex = '\A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z';
my $versionminorregex = '\A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z';
@@ -43,7 +44,6 @@ my $wikiurl = 'https://wiki.libsdl.org';
my $bugreporturl = 'https://github.com/libsdl-org/sdlwiki/issues/new';
my $srcpath = undef;
my $wikipath = undef;
my $wikireadmesubdir = 'README';
my $warn_about_missing = 0;
my $copy_direction = 0;
my $optionsfname = undef;
@@ -111,6 +111,7 @@ if (defined $optionsfname) {
$srcpath = $val, next if $key eq 'srcpath';
$wikipath = $val, next if $key eq 'wikipath';
$apiprefixregex = $val, next if $key eq 'apiprefixregex';
$apipropertyregex = $val, next if $key eq 'apipropertyregex';
$projectfullname = $val, next if $key eq 'projectfullname';
$projectshortname = $val, next if $key eq 'projectshortname';
$wikisubdir = $val, next if $key eq 'wikisubdir';
@@ -427,6 +428,7 @@ sub dewikify_chunk {
# make sure these can't become part of roff syntax.
$str =~ s/\./\\[char46]/gms;
$str =~ s/"/\\(dq/gms;
$str =~ s/'/\\(aq/gms;
if ($wikitype eq 'mediawiki') {
# Dump obvious wikilinks.
@@ -825,21 +827,23 @@ sub print_big_ascii_string {
die("Don't have a big ascii entry for '$ch'!\n") if not defined $rowsref;
my $row = @$rowsref[$rownum];
my $outstr = '';
if ($lowascii) {
my @x = split //, $row;
foreach (@x) {
my $v = ($_ eq "\x{2588}") ? 'X' : ' ';
print $fh $v;
$outstr .= ($_ eq "\x{2588}") ? 'X' : ' ';
}
} else {
print $fh $row;
$outstr = $row;
}
$charidx++;
if ($charidx < $charcount) {
print $fh " ";
if ($charidx == $charcount) {
$outstr =~ s/\s*\Z//; # dump extra spaces at the end of the line.
} else {
$outstr .= ' '; # space between glyphs.
}
print $fh $outstr;
}
print $fh "\n";
}
@@ -1033,7 +1037,6 @@ sub generate_quickref {
my $incpath = "$srcpath";
$incpath .= "/$incsubdir" if $incsubdir ne '';
my $wikireadmepath = "$wikipath/$wikireadmesubdir";
my $readmepath = undef;
if (defined $readmesubdir) {
$readmepath = "$srcpath/$readmesubdir";
@@ -1365,7 +1368,7 @@ while (my $d = readdir(DH)) {
# update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text.
# At Sam's request, don't list property defines with functions. (See #9440)
my $is_property = /\A\s*\#\s*define\s+SDL_PROP_/;
my $is_property = (defined $apipropertyregex) ? /$apipropertyregex/ : 0;
if (!$is_property) {
if ($blank_lines > 0) {
while ($blank_lines > 0) {
@@ -2082,19 +2085,16 @@ if ($copy_direction == 1) { # --copy-to-headers
}
if (defined $readmepath) {
if ( -d $wikireadmepath ) {
mkdir($readmepath); # just in case
opendir(DH, $wikireadmepath) or die("Can't opendir '$wikireadmepath': $!\n");
opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n");
while (readdir(DH)) {
my $dent = $_;
if ($dent =~ /\A(.*?)\.md\Z/) { # we only bridge Markdown files here.
next if $1 eq 'FrontPage';
filecopy("$wikireadmepath/$dent", "$readmepath/README-$dent", "\n");
if ($dent =~ /\AREADME\-.*?\.md\Z/) { # we only bridge Markdown files here that start with "README-".
filecopy("$wikipath/$dent", "$readmepath/$dent", "\n");
}
}
closedir(DH);
}
}
} elsif ($copy_direction == -1) { # --copy-to-wiki
@@ -2698,31 +2698,27 @@ __EOF__
# Write out READMEs...
if (defined $readmepath) {
if ( -d $readmepath ) {
mkdir($wikireadmepath); # just in case
mkdir($wikipath); # just in case
opendir(DH, $readmepath) or die("Can't opendir '$readmepath': $!\n");
while (my $d = readdir(DH)) {
my $dent = $d;
if ($dent =~ /\AREADME\-(.*?\.md)\Z/) { # we only bridge Markdown files here.
my $wikifname = $1;
next if $wikifname eq 'FrontPage.md';
filecopy("$readmepath/$dent", "$wikireadmepath/$wikifname", "\n");
if ($dent =~ /\AREADME\-.*?\.md\Z/) { # we only bridge Markdown files here that start with "README-".
filecopy("$readmepath/$dent", "$wikipath/$dent", "\n");
}
}
closedir(DH);
my @pages = ();
opendir(DH, $wikireadmepath) or die("Can't opendir '$wikireadmepath': $!\n");
opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n");
while (my $d = readdir(DH)) {
my $dent = $d;
if ($dent =~ /\A(.*?)\.(mediawiki|md)\Z/) {
my $wikiname = $1;
next if $wikiname eq 'FrontPage';
push @pages, $wikiname;
if ($dent =~ /\A(README\-.*?)\.md\Z/) {
push @pages, $1;
}
}
closedir(DH);
open(FH, '>', "$wikireadmepath/FrontPage.md") or die("Can't open '$wikireadmepath/FrontPage.md': $!\n");
open(FH, '>', "$wikipath/READMEs.md") or die("Can't open '$wikipath/READMEs.md': $!\n");
print FH "# All READMEs available here\n\n";
foreach (sort @pages) {
my $wikiname = $_;
@@ -2980,10 +2976,12 @@ __EOF__
}
if (defined $returns) {
# Check for md link in return type: ([SDL_Renderer](SDL_Renderer) *)
# This would've prevented the next regex from working properly (it'd leave " *)")
$returns =~ s/\A\(\[.*?\]\((.*?)\)/\($1/ms;
# Chop datatype in parentheses off the front.
if(!($returns =~ s/\A\([^\[]*\[[^\]]*\]\([^\)]*\)[^\)]*\) //ms)) {
$returns =~ s/\A\([^\)]*\) //ms;
}
$returns =~ s/\A\(.*?\) //;
$returns = dewikify($wikitype, $returns);
$str .= ".SH RETURN VALUE\n";
$str .= "$returns\n";

View File

@@ -0,0 +1,189 @@
if(NGAGESDK)
function(SDL_Preseed_CMakeCache)
set(COMPILER_SUPPORTS_ARMNEON "" CACHE INTERNAL "Test COMPILER_SUPPORTS_ARMNEON")
set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS "" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS")
set(COMPILER_SUPPORTS_SYNC_LOCK_TEST_AND_SET "" CACHE INTERNAL "Test COMPILER_SUPPORTS_SYNC_LOCK_TEST_AND_SET")
set(HAVE_CLANG_COMMENT_BLOCK_COMMANDS "" CACHE INTERNAL "Test HAVE_CLANG_COMMENT_BLOCK_COMMANDS")
set(HAVE_ALLOCA_H "" CACHE INTERNAL "Have include alloca.h")
set(HAVE_LIBM "1" CACHE INTERNAL "Have library m")
set(HAVE_POSIX_SPAWN "" CACHE INTERNAL "Have symbol posix_spawn")
set(HAVE_MALLOC "1" CACHE INTERNAL "Have include malloc.h")
set(LIBC_HAS_ABS "1" CACHE INTERNAL "Have symbol abs")
set(LIBC_HAS_ACOS "1" CACHE INTERNAL "Have symbol acos")
set(LIBC_HAS_ACOSF "" CACHE INTERNAL "Have symbol acosf")
set(LIBC_HAS_ASIN "1" CACHE INTERNAL "Have symbol asin")
set(LIBC_HAS_ASINF "" CACHE INTERNAL "Have symbol asinf")
set(LIBC_HAS_ATAN "1" CACHE INTERNAL "Have symbol atan")
set(LIBC_HAS_ATAN2 "1" CACHE INTERNAL "Have symbol atan2")
set(LIBC_HAS_ATAN2F "" CACHE INTERNAL "Have symbol atan2f")
set(LIBC_HAS_ATANF "" CACHE INTERNAL "Have symbol atanf")
set(LIBC_HAS_ATOF "" CACHE INTERNAL "Have symbol atof")
set(LIBC_HAS_ATOI "" CACHE INTERNAL "Have symbol atoi")
set(LIBC_HAS_BCOPY "1" CACHE INTERNAL "Have symbol bcopy")
set(LIBC_HAS_CALLOC "" CACHE INTERNAL "Have symbol calloc")
set(LIBC_HAS_CEIL "1" CACHE INTERNAL "Have symbol ceil")
set(LIBC_HAS_CEILF "" CACHE INTERNAL "Have symbol ceilf")
set(LIBC_HAS_COPYSIGN "1" CACHE INTERNAL "Have symbol copysign")
set(LIBC_HAS_COPYSIGNF "1" CACHE INTERNAL "Have symbol copysignf")
set(LIBC_HAS_COS "1" CACHE INTERNAL "Have symbol cos")
set(LIBC_HAS_COSF "" CACHE INTERNAL "Have symbol cosf")
set(LIBC_HAS_EXP "1" CACHE INTERNAL "Have symbol exp")
set(LIBC_HAS_EXPF "" CACHE INTERNAL "Have symbol expf")
set(LIBC_HAS_FABS "1" CACHE INTERNAL "Have symbol fabs")
set(LIBC_HAS_FABSF "1" CACHE INTERNAL "Have symbol fabsf")
set(LIBC_HAS_FLOAT_H "1" CACHE INTERNAL "Have include float.h")
set(LIBC_HAS_FLOOR "1" CACHE INTERNAL "Have symbol floor")
set(LIBC_HAS_FLOORF "" CACHE INTERNAL "Have symbol floorf")
set(LIBC_HAS_FMOD "" CACHE INTERNAL "Have symbol fmod")
set(LIBC_HAS_FMODF "" CACHE INTERNAL "Have symbol fmodf")
set(LIBC_HAS_FOPEN64 "" CACHE INTERNAL "Have symbol fopen64")
set(LIBC_HAS_FREE "1" CACHE INTERNAL "Have symbol free")
set(LIBC_HAS_FSEEKO "" CACHE INTERNAL "Have symbol fseeko")
set(LIBC_HAS_FSEEKO64 "" CACHE INTERNAL "Have symbol fseeko64")
set(LIBC_HAS_GETENV "" CACHE INTERNAL "Have symbol getenv")
set(LIBC_HAS_ICONV_H "" CACHE INTERNAL "Have include iconv.h")
set(LIBC_HAS_INDEX "1" CACHE INTERNAL "Have symbol index")
set(LIBC_HAS_INTTYPES_H "1" CACHE INTERNAL "Have include inttypes.h")
set(LIBC_HAS_ISINF "1" CACHE INTERNAL "Have include isinf(double)")
set(LIBC_ISINF_HANDLES_FLOAT "1" CACHE INTERNAL "Have include isinf(float)")
set(LIBC_HAS_ISINFF "1" CACHE INTERNAL "Have include isinff(float)")
set(LIBC_HAS_ISNAN "1" CACHE INTERNAL "Have include isnan(double)")
set(LIBC_ISNAN_HANDLES_FLOAT "1" CACHE INTERNAL "Have include isnan(float)")
set(LIBC_HAS_ISNANF "1" CACHE INTERNAL "Have include isnanf(float)")
set(LIBC_HAS_ITOA "" CACHE INTERNAL "Have symbol itoa")
set(LIBC_HAS_LIMITS_H "1" CACHE INTERNAL "Have include limits.h")
set(LIBC_HAS_LOG "1" CACHE INTERNAL "Have symbol log")
set(LIBC_HAS_LOG10 "" CACHE INTERNAL "Have symbol log10")
set(LIBC_HAS_LOG10F "" CACHE INTERNAL "Have symbol log10f")
set(LIBC_HAS_LOGF "" CACHE INTERNAL "Have symbol logf")
set(LIBC_HAS_LROUND "" CACHE INTERNAL "Have symbol lround")
set(LIBC_HAS_LROUNDF "" CACHE INTERNAL "Have symbol lroundf")
set(LIBC_HAS_MALLOC "1" CACHE INTERNAL "Have symbol malloc")
set(LIBC_HAS_MALLOC_H "" CACHE INTERNAL "Have include malloc.h")
set(LIBC_HAS_MATH_H "1" CACHE INTERNAL "Have include math.h")
set(LIBC_HAS_MEMCMP "1" CACHE INTERNAL "Have symbol memcmp")
set(LIBC_HAS_MEMCPY "" CACHE INTERNAL "Have symbol memcpy")
set(LIBC_HAS_MEMMOVE "" CACHE INTERNAL "Have symbol memmove")
set(LIBC_HAS_MEMORY_H "" CACHE INTERNAL "Have include memory.h")
set(LIBC_HAS_MEMSET "" CACHE INTERNAL "Have symbol memset")
set(LIBC_HAS_MODF "1" CACHE INTERNAL "Have symbol modf")
set(LIBC_HAS_MODFF "" CACHE INTERNAL "Have symbol modff")
set(LIBC_HAS_POW "1" CACHE INTERNAL "Have symbol pow")
set(LIBC_HAS_POWF "" CACHE INTERNAL "Have symbol powf")
set(LIBC_HAS_PUTENV "" CACHE INTERNAL "Have symbol putenv")
set(LIBC_HAS_REALLOC "" CACHE INTERNAL "Have symbol realloc")
set(LIBC_HAS_RINDEX "1" CACHE INTERNAL "Have symbol rindex")
set(LIBC_HAS_ROUND "" CACHE INTERNAL "Have symbol round")
set(LIBC_HAS_ROUNDF "" CACHE INTERNAL "Have symbol roundf")
set(LIBC_HAS_SCALBN "1" CACHE INTERNAL "Have symbol scalbn")
set(LIBC_HAS_SCALBNF "" CACHE INTERNAL "Have symbol scalbnf")
set(LIBC_HAS_SETENV "" CACHE INTERNAL "Have symbol setenv")
set(LIBC_HAS_SIGNAL_H "" CACHE INTERNAL "Have include signal.h")
set(LIBC_HAS_SIN "1" CACHE INTERNAL "Have symbol sin")
set(LIBC_HAS_SINF "" CACHE INTERNAL "Have symbol sinf")
set(LIBC_HAS_SQR "" CACHE INTERNAL "Have symbol sqr")
set(LIBC_HAS_SQRT "1" CACHE INTERNAL "Have symbol sqrt")
set(LIBC_HAS_SQRTF "" CACHE INTERNAL "Have symbol sqrtf")
set(LIBC_HAS_SSCANF "1" CACHE INTERNAL "Have symbol sscanf")
set(LIBC_HAS_STDARG_H "1" CACHE INTERNAL "Have include stdarg.h")
set(LIBC_HAS_STDBOOL_H "1" CACHE INTERNAL "Have include stdbool.h")
set(LIBC_HAS_STDDEF_H "1" CACHE INTERNAL "Have include stddef.h")
set(LIBC_HAS_STDINT_H "1" CACHE INTERNAL "Have include stdint.h")
set(LIBC_HAS_STDIO_H "1" CACHE INTERNAL "Have include stdio.h")
set(LIBC_HAS_STDLIB_H "1" CACHE INTERNAL "Have include stdlib.h")
set(LIBC_HAS_STRCASESTR "" CACHE INTERNAL "Have symbol strcasestr")
set(LIBC_HAS_STRCHR "1" CACHE INTERNAL "Have symbol strchr")
set(LIBC_HAS_STRCMP "1" CACHE INTERNAL "Have symbol strcmp")
set(LIBC_HAS_STRINGS_H "" CACHE INTERNAL "Have include strings.h")
set(LIBC_HAS_STRING_H "1" CACHE INTERNAL "Have include string.h")
set(LIBC_HAS_STRLCAT "" CACHE INTERNAL "Have symbol strlcat")
set(LIBC_HAS_STRLCPY "" CACHE INTERNAL "Have symbol strlcpy")
set(LIBC_HAS_STRLEN "1" CACHE INTERNAL "Have symbol strlen")
set(LIBC_HAS_STRNCMP "1" CACHE INTERNAL "Have symbol strncmp")
set(LIBC_HAS_STRNLEN "" CACHE INTERNAL "Have symbol strnlen")
set(LIBC_HAS_STRNSTR "" CACHE INTERNAL "Have symbol strnstr")
set(LIBC_HAS_STRPBRK "1" CACHE INTERNAL "Have symbol strpbrk")
set(LIBC_HAS_STRRCHR "1" CACHE INTERNAL "Have symbol strrchr")
set(LIBC_HAS_STRSTR "1" CACHE INTERNAL "Have symbol strstr")
set(LIBC_HAS_STRTOD "" CACHE INTERNAL "Have symbol strtod")
set(LIBC_HAS_STRTOK_R "" CACHE INTERNAL "Have symbol strtok_r")
set(LIBC_HAS_STRTOL "" CACHE INTERNAL "Have symbol strtol")
set(LIBC_HAS_STRTOLL "" CACHE INTERNAL "Have symbol strtoll")
set(LIBC_HAS_STRTOUL "" CACHE INTERNAL "Have symbol strtoul")
set(LIBC_HAS_STRTOULL "" CACHE INTERNAL "Have symbol strtoull")
set(LIBC_HAS_SYS_TYPES_H "1" CACHE INTERNAL "Have include sys/types.h")
set(LIBC_HAS_TAN "1" CACHE INTERNAL "Have symbol tan")
set(LIBC_HAS_TANF "" CACHE INTERNAL "Have symbol tanf")
set(LIBC_HAS_TIME_H "1" CACHE INTERNAL "Have include time.h")
set(LIBC_HAS_TRUNC "" CACHE INTERNAL "Have symbol trunc")
set(LIBC_HAS_TRUNCF "" CACHE INTERNAL "Have symbol truncf")
set(LIBC_HAS_UNSETENV "" CACHE INTERNAL "Have symbol unsetenv")
set(LIBC_HAS_VSNPRINTF "" CACHE INTERNAL "Have symbol vsnprintf")
set(LIBC_HAS_VSSCANF "" CACHE INTERNAL "Have symbol vsscanf")
set(LIBC_HAS_WCHAR_H "1" CACHE INTERNAL "Have include wchar.h")
set(LIBC_HAS_WCSCMP "" CACHE INTERNAL "Have symbol wcscmp")
set(LIBC_HAS_WCSDUP "" CACHE INTERNAL "Have symbol wcsdup")
set(LIBC_HAS_WCSLCAT "" CACHE INTERNAL "Have symbol wcslcat")
set(LIBC_HAS_WCSLCPY "" CACHE INTERNAL "Have symbol wcslcpy")
set(LIBC_HAS_WCSLEN "" CACHE INTERNAL "Have symbol wcslen")
set(LIBC_HAS_WCSNCMP "" CACHE INTERNAL "Have symbol wcsncmp")
set(LIBC_HAS_WCSNLEN "" CACHE INTERNAL "Have symbol wcsnlen")
set(LIBC_HAS_WCSSTR "" CACHE INTERNAL "Have symbol wcsstr")
set(LIBC_HAS_WCSTOL "" CACHE INTERNAL "Have symbol wcstol")
set(LIBC_HAS__EXIT "" CACHE INTERNAL "Have symbol _Exit")
set(LIBC_HAS__I64TOA "" CACHE INTERNAL "Have symbol _i64toa")
set(LIBC_HAS__LTOA "" CACHE INTERNAL "Have symbol _ltoa")
set(LIBC_HAS__STRREV "" CACHE INTERNAL "Have symbol _strrev")
set(LIBC_HAS__UI64TOA "" CACHE INTERNAL "Have symbol _ui64toa")
set(LIBC_HAS__UITOA "" CACHE INTERNAL "Have symbol _uitoa")
set(LIBC_HAS__ULTOA "" CACHE INTERNAL "Have symbol _ultoa")
set(LIBC_HAS__WCSDUP "" CACHE INTERNAL "Have symbol _wcsdup")
set(LIBC_IS_GLIBC "" CACHE INTERNAL "Have symbol __GLIBC__")
set(_ALLOCA_IN_MALLOC_H "" CACHE INTERNAL "Have symbol _alloca")
set(HAVE_GCC_WALL "1" CACHE INTERNAL "Test HAVE_GCC_WALL")
set(HAVE_GCC_WUNDEF "1" CACHE INTERNAL "Test HAVE_GCC_WUNDEF")
set(HAVE_GCC_WFLOAT_CONVERSION "" CACHE INTERNAL "Test HAVE_GCC_WFLOAT_CONVERSION")
set(HAVE_GCC_NO_STRICT_ALIASING "1" CACHE INTERNAL "Test HAVE_GCC_NO_STRICT_ALIASING")
set(HAVE_GCC_WDOCUMENTATION "" CACHE INTERNAL "Test HAVE_GCC_WDOCUMENTATION")
set(HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND "" CACHE INTERNAL "Test HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND")
set(HAVE_GCC_COMMENT_BLOCK_COMMANDS "" CACHE INTERNAL "Test HAVE_GCC_COMMENT_BLOCK_COMMANDS")
set(HAVE_GCC_WSHADOW "1" CACHE INTERNAL "Test HAVE_GCC_WSHADOW")
set(HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS "" CACHE INTERNAL "Test HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS")
set(HAVE_GCC_WIMPLICIT_FALLTHROUGH "" CACHE INTERNAL "Test HAVE_GCC_WIMPLICIT_FALLTHROUGH")
set(HAVE_GCC_FVISIBILITY "" CACHE INTERNAL "Test HAVE_GCC_FVISIBILITY")
set(HAVE_ST_MTIM "" CACHE INTERNAL "Test HAVE_ST_MTIM")
#set(HAVE_O_CLOEXEC "" CACHE INTERNAL "Test HAVE_O_CLOEXEC")
#set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR "" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR")
set(COMPILER_SUPPORTS_GCC_ATOMICS "" CACHE INTERNAL "Test COMPILER_SUPPORTS_GCC_ATOMICS")
set(LINKER_SUPPORTS_VERSION_SCRIPT "" CACHE INTERNAL "Test LINKER_SUPPORTS_VERSION_SCRIPT")
set(LINKER_SUPPORTS_WL_NO_UNDEFINED "" CACHE INTERNAL "Test LINKER_SUPPORTS_WL_NO_UNDEFINED")
set(ICONV_IN_LIBC "" CACHE INTERNAL "Test ICONV_IN_LIBC")
set(ICONV_IN_LIBICONV "" CACHE INTERNAL "Test ICONV_IN_LIBICONV")
#set(LIBC_HAS_WORKING_LIBUNWIND "" CACHE INTERNAL "Test LIBC_HAS_WORKING_LIBUNWIND")
#set(LIBUNWIND_HAS_WORKINGLIBUNWIND "" CACHE INTERNAL "Test LIBUNWIND_HAS_WORKINGLIBUNWIND")
set(HAVE_GETPAGESIZE "" CACHE INTERNAL "Have symbol getpagesize")
set(HAVE_SIGACTION "" CACHE INTERNAL "Have symbol sigaction")
set(HAVE_SA_SIGACTION "" CACHE INTERNAL "Have symbol sa_sigaction")
set(HAVE_SETJMP "" CACHE INTERNAL "Have symbol setjmp")
set(HAVE_NANOSLEEP "" CACHE INTERNAL "Have symbol nanosleep")
set(HAVE_GMTIME_R "" CACHE INTERNAL "Have symbol gmtime_r")
set(HAVE_LOCALTIME_R "" CACHE INTERNAL "Have symbol localtime_r")
set(HAVE_NL_LANGINFO "" CACHE INTERNAL "Have symbol nl_langinfo")
set(HAVE_SYSCONF "" CACHE INTERNAL "Have symbol sysconf")
set(HAVE_SYSCTLBYNAME "" CACHE INTERNAL "Have symbol sysctlbyname")
set(HAVE_GETAUXVAL "" CACHE INTERNAL "Have symbol getauxval")
set(HAVE_ELF_AUX_INFO "" CACHE INTERNAL "Have symbol elf_aux_info")
set(HAVE_POLL "" CACHE INTERNAL "Have symbol poll")
set(HAVE_MEMFD_CREATE "" CACHE INTERNAL "Have symbol memfd_create")
set(HAVE_POSIX_FALLOCATE "" CACHE INTERNAL "Have symbol posix_fallocate")
set(HAVE_DLOPEN_IN_LIBC "" CACHE INTERNAL "Have symbol dlopen")
set(HAVE_GETHOSTNAME "" CACHE INTERNAL "Have symbol gethostname")
set(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR "" CACHE INTERNAL "Have symbol addchdir")
set(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP "" CACHE INTERNAL "Have symbol addchdir_np")
set(HAVE_FDATASYNC "" CACHE INTERNAL "Have symbol fdatasync")
set(HAVE_SDL_FSOPS "1" CACHE INTERNAL "Enable SDL_FSOPS")
set(HAVE_SDL_LOCALE "1" CACHE INTERNAL "Enable SDL_LOCALE")
endfunction()
endif()

View File

@@ -594,6 +594,18 @@ macro(CheckWayland)
sdl_link_dependency(wayland LIBS PkgConfig::PC_WAYLAND PKG_CONFIG_PREFIX PC_WAYLAND PKG_CONFIG_SPECS ${WAYLAND_PKG_CONFIG_SPEC})
endif()
# xkbcommon doesn't provide internal version defines, so generate them here.
if (PC_WAYLAND_xkbcommon_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)")
set(SDL_XKBCOMMON_VERSION_MAJOR ${CMAKE_MATCH_1})
set(SDL_XKBCOMMON_VERSION_MINOR ${CMAKE_MATCH_2})
set(SDL_XKBCOMMON_VERSION_PATCH ${CMAKE_MATCH_3})
else()
message(WARNING "Failed to parse xkbcommon version; defaulting to lowest supported (0.5.0)")
set(SDL_XKBCOMMON_VERSION_MAJOR 0)
set(SDL_XKBCOMMON_VERSION_MINOR 5)
set(SDL_XKBCOMMON_VERSION_PATCH 0)
endif()
if(SDL_WAYLAND_LIBDECOR)
set(LibDecor_PKG_CONFIG_SPEC libdecor-0)
pkg_check_modules(PC_LIBDECOR IMPORTED_TARGET ${LibDecor_PKG_CONFIG_SPEC})
@@ -814,7 +826,7 @@ endmacro()
macro(CheckPTHREAD)
cmake_push_check_state()
if(SDL_PTHREADS)
if(ANDROID)
if(ANDROID OR SDL_PTHREADS_PRIVATE)
# the android libc provides built-in support for pthreads, so no
# additional linking or compile flags are necessary
elseif(LINUX)

View File

@@ -22,6 +22,8 @@ function(SDL_DetectCMakePlatform)
set(sdl_cmake_platform Haiku)
elseif(NINTENDO_3DS)
set(sdl_cmake_platform n3ds)
elseif(NGAGESDK)
set(sdl_cmake_platform ngage)
elseif(PS2)
set(sdl_cmake_platform ps2)
elseif(VITA)

View File

@@ -96,12 +96,14 @@ if(TEST_STATIC)
add_executable(gui-static WIN32 main_gui.c)
target_link_libraries(gui-static PRIVATE SDL3::SDL3-static)
if(TEST_SHARED)
# Assume SDL library has been built with `set(CMAKE_POSITION_INDEPENDENT_CODE ON)`
add_library(sharedlib-static SHARED main_lib.c)
target_link_libraries(sharedlib-static PRIVATE SDL3::SDL3-static)
generate_export_header(sharedlib-static EXPORT_MACRO_NAME MYLIBRARY_EXPORT)
target_compile_definitions(sharedlib-static PRIVATE "EXPORT_HEADER=\"${CMAKE_CURRENT_BINARY_DIR}/sharedlib-static_export.h\"")
set_target_properties(sharedlib-static PROPERTIES C_VISIBILITY_PRESET "hidden")
endif()
if(TEST_TEST)
add_executable(sdltest-static sdltest.c)

View File

@@ -1,24 +1,37 @@
#include <SDL3/SDL.h>
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL_main.h>
#include <SDL3/SDL.h>
int main(int argc, char *argv[])
static SDL_Window *window;
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_Window *window = NULL;
SDL_Surface *screenSurface = NULL;
screenSurface = SDL_GetWindowSurface(window);
SDL_FillSurfaceRect(screenSurface, NULL, SDL_MapSurfaceRGB(screenSurface, 0xff, 0xff, 0xff));
SDL_UpdateWindowSurface(window);
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Could not initialize SDL: %s", SDL_GetError());
return 1;
return SDL_APP_FAILURE;
}
window = SDL_CreateWindow("Hello SDL", 640, 480, 0);
if (!window) {
SDL_Log("could not create window: %s", SDL_GetError());
return 1;
return SDL_APP_FAILURE;
}
screenSurface = SDL_GetWindowSurface(window);
SDL_FillSurfaceRect(screenSurface, NULL, SDL_MapSurfaceRGB(screenSurface, 0xff, 0xff, 0xff));
SDL_UpdateWindowSurface(window);
SDL_Delay(100);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void *appstate, SDL_AppResult result) {
SDL_DestroyWindow(window);
}

View File

@@ -1,9 +1,24 @@
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
return SDL_APP_SUCCESS;
}
int main(int argc, char *argv[]) {
SDL_AppResult SDL_AppIterate(void *appstate)
{
return SDL_APP_SUCCESS;
}
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDLTest_CommonState state;
SDLTest_CommonDefaultArgs(&state, argc, argv);
return 0;
return SDL_APP_SUCCESS;
}
void SDL_AppQuit(void *appstate, SDL_AppResult result) {
}

View File

@@ -157,7 +157,7 @@ flags to the compiler.
- Use [`CMAKE_EXE_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS.html) to pass extra option to the linker for executables.
- Use [`CMAKE_SHARED_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS.html) to pass extra options to the linker for shared libraries.
#### Examples
#### Compile Options Examples
- build a SDL library optimized for (more) modern x64 microprocessor architectures.
@@ -240,7 +240,7 @@ Append with a version number to target a specific SDK revision: e.g. `iphoneos12
CMake documentation: [link](https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_SYSROOT.html)
#### Examples
#### Apple Examples
- for macOS, building a dylib and/or static library for x86_64 and arm64:
@@ -328,7 +328,7 @@ Configure your project with `-DSDL_LIBC=ON` to make use of sanitizers.
### CMake fails to build without X11 or Wayland support
Install the required system packages prior to running CMake.
See [README-linux](linux#build-dependencies) for the list of dependencies on Linux.
See [README-linux.md](README-linux.md#build-dependencies) for the list of dependencies on Linux.
Other unix operating systems should provide similar packages.
If you **really** don't need to show windows, add `-DSDL_UNIX_CONSOLE_BUILD=ON` to the CMake configure command.

View File

@@ -34,6 +34,12 @@ things, you might confuse it. This is to the benefit of documentation, though,
where we would rather you not do surprising things.
## UTF-8 only!
All text must be UTF-8 encoded. The wiki will refuse to update files that are
malformed.
## We _sort of_ write in Doxygen format.
To document a symbol, we use something that looks like Doxygen (and Javadoc)
@@ -327,6 +333,16 @@ If you add Doxygen with a `##` (`###`, etc) section header, it'll
migrate to the wiki and be _removed_ from the headers. Generally
the correct thing to do is _never use section headers in the Doxygen_.
## wikiheaders will reorder standard sections.
The standard sections are always kept in a consistent order by
wikiheaders, both in the headers and the wiki. If they're placed in
a non-standard order, wikiheaders will reorder them.
For sections that aren't standard, wikiheaders will place them at
the end of the wiki page, in the order they were seen when it loaded
the page for processing.
## It's okay to repeat yourself.
Each individual piece of documentation becomes a separate page on the wiki, so
@@ -340,7 +356,7 @@ through, header users can search for the function name.
You might be reading this document on the wiki! Any `README-*.md` files in
the docs directory are bridged to the wiki, so `docs/README-linux.md` lands
at https://wiki.libsdl.org/SDL3/README/linux ...these are just copied directly
at https://wiki.libsdl.org/SDL3/README-linux ...these are just copied directly
without any further processing by wikiheaders, and changes go in both
directions.

View File

@@ -103,7 +103,7 @@ getting started.
Another option is to use SDL' main callbacks, which handle this for you
without platform-specific code in your app. Please refer to
[the wiki](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3)
[the wiki](https://wiki.libsdl.org/SDL3/README-main-functions#main-callbacks-in-sdl3)
or `docs/README-main-functions.md` in the SDL source code.
@@ -230,7 +230,7 @@ tools.
mkdir build
cd build
emcmake cmake ..
# you can also do `emcmake cmake -G Ninja ..` and then use `ninja` instead of this command.
# you can also try `emcmake cmake -G Ninja ..` and then use `ninja` instead of this command.
emmake make -j4
```

View File

@@ -46,6 +46,7 @@ openSUSE Tumbleweed:
libgbm-devel pipewire-devel libpulse-devel sndio-devel Mesa-libEGL-devel
Arch:
sudo pacman -S alsa-lib cmake hidapi ibus jack libdecor libgl libpulse libusb libx11 libxcursor libxext libxinerama libxkbcommon libxrandr libxrender libxss libxtst mesa ninja pipewire sndio vulkan-driver vulkan-headers wayland wayland-protocols

View File

@@ -1,5 +1,64 @@
Support for the Nokia N-Gage has been removed from SDL3 (but will make a
comeback when newer compilers are available for the platform).
# Nokia N-Gage
SDL2 still supports this platform.
SDL port for the Nokia N-Gage
[Homebrew toolchain](https://github.com/ngagesdk/ngage-toolchain)
contributed by:
- [Michael Fitzmayer](https://github.com/mupfdev)
- [Anonymous Maarten](https://github.com/madebr)
Many thanks to:
- icculus and slouken for always making room for us, even when we show up in 2025
still waving the N-Gage flag.
- The Nokia N-Gage [Discord community](https://discord.gg/dbUzqJ26vs)
who keeps the platform alive.
- The staff and supporters of the
[Suomen pelimuseo](https://www.vapriikki.fi/nayttelyt/fantastinen-floppi/), and
to Heikki Jungmann, for their ongoing love and dedication for the Nokia N-Gage --
you guys are awesome!
## History
When SDL support was discontinued due to the lack of C99 support at the time,
this version was rebuilt from the ground up after resolving the compiler issues.
In contrast to the earlier SDL2 port, this version features a dedicated rendering
backend and a functional, albeit limited, audio interface. Support for the
software renderer has been removed.
The outcome is a significantly leaner and more efficient SDL port, which we hope
will breathe new life into this beloved yet obscure platform.
## To the Stubborn Legends of the DC Scene
This port is lovingly dedicated to the ever-nostalgic Dreamcast homebrew scene --
because if we managed to pull this off for the N-Gage (yes, the N-Gage), surely
you guys can stop clinging to SDL2 like it's a rare Shenmue prototype and finally
make the leap to SDL3. It's 2025, not 1999 -- and let's be honest, you're rocking
a state-of-the-art C23 compiler. The irony writes itself.
## Existing Issues and Limitations
- For now, the new
[SDL3 main callbacks](https://wiki.libsdl.org/SDL3/README/main-functions#how-to-use-main-callbacks-in-sdl3)
are not optional and must be used. This is important as the callbacks
are optional on other platforms.
- If the application is put in the background while sound is playing,
some of the audio is looped until the app is back in focus.
- It is recommended initialising SDLs audio sub-system even when it
is not required. The backend is started at a higher level. Initialising
SDLs audio sub-system ensures that the backend is properly deinitialised.
- Because the audio sample rate can change during phone calls, the sample
rate is currently fixed at 8kHz to ensure stable behavior. Although
dynamically adjusting the sample rate is theoretically possible, the
current implementation doesn't support it yet. This limitation is
expected to be resolved in a future update.
- Dependency tracking is currently non-functional.

View File

@@ -11,7 +11,7 @@
- [macOS](README-macos.md)
- [NetBSD](README-bsd.md)
- [Nintendo Switch](README-switch.md)
- [Nintendo 3DS](README-3ds.md)
- [Nintendo 3DS](README-n3ds.md)
- [OpenBSD](README-bsd.md)
- [PlayStation 2](README-ps2.md)
- [PlayStation 4](README-ps4.md)
@@ -24,6 +24,7 @@
- [Windows](README-windows.md)
- [Windows GDK](README-gdk.md)
- [Xbox](README-gdk.md)
- [Nokia N-Gage](README-ngage.md)
## Unsupported Platforms
@@ -33,7 +34,6 @@ All of these still work with [SDL2](/SDL2), which is an incompatible API, but an
- Google Stadia
- NaCL
- Nokia N-Gage
- OS/2
- QNX
- WinPhone

View File

@@ -59,6 +59,15 @@ encounter limitations or behavior that is different from other windowing systems
`SDL_APP_ID` hint string, the desktop entry file name should match the application ID. For example, if your
application ID is set to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`.
### The application progress bar can't be set via ```SDL_SetWindowProgressState()``` or ```SDL_SetWindowProgressValue()```
- Only some Desktop Environemnts support the underlying API. Known compatible DEs: Unity, KDE
- The underlying API requires a desktop entry file, aka a `.desktop` file.
Please see the [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/latest/) for
more information on the format of this file. Note that if your application manually sets the application ID via the
`SDL_APP_ID` hint string, the desktop entry file name should match the application ID. For example, if your
application ID is set to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`.
### Keyboard grabs don't work when running under XWayland
- On GNOME based desktops, the dconf setting `org/gnome/mutter/wayland/xwayland-allow-grabs` must be enabled.

View File

@@ -111,6 +111,10 @@ macro(add_sdl_example_executable TARGET)
elseif(EMSCRIPTEN)
set_property(TARGET ${TARGET} PROPERTY SUFFIX ".html")
target_link_options(${TARGET} PRIVATE -sALLOW_MEMORY_GROWTH=1)
elseif(NGAGE)
string(MD5 TARGET_MD5 "${TARGET}")
string(SUBSTRING "${TARGET_MD5}" 0 8 TARGET_MD5_8)
target_link_options(${TARGET} PRIVATE "SHELL:-s UID3=0x${TARGET_MD5_8}")
endif()
if(OPENGL_FOUND)
@@ -141,6 +145,7 @@ add_sdl_example_executable(audio-simple-playback SOURCES audio/01-simple-playbac
add_sdl_example_executable(audio-simple-playback-callback SOURCES audio/02-simple-playback-callback/simple-playback-callback.c)
add_sdl_example_executable(audio-load-wav SOURCES audio/03-load-wav/load-wav.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav)
add_sdl_example_executable(audio-multiple-streams SOURCES audio/04-multiple-streams/multiple-streams.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav ${CMAKE_CURRENT_SOURCE_DIR}/../test/sword.wav)
add_sdl_example_executable(audio-planar-data SOURCES audio/05-planar-data/planar-data.c)
add_sdl_example_executable(input-joystick-polling SOURCES input/01-joystick-polling/joystick-polling.c)
add_sdl_example_executable(input-joystick-events SOURCES input/02-joystick-events/joystick-events.c)
add_sdl_example_executable(camera-read-and-draw SOURCES camera/01-read-and-draw/read-and-draw.c)

View File

@@ -1,5 +1,5 @@
If you're running this in a web browser, you need to click the window before you'll hear anything!
This example code loads two .wav files, puts them an audio streams and binds
This example code loads two .wav files, puts them in audio streams and binds
them for playback, repeating both sounds on loop. This shows several streams
mixing into a single playback device.

View File

@@ -1,5 +1,5 @@
/*
* This example code loads two .wav files, puts them an audio streams and
* This example code loads two .wav files, puts them in audio streams and
* binds them for playback, repeating both sounds on loop. This shows several
* streams mixing into a single playback device.
*

View File

@@ -0,0 +1,7 @@
This example code draws two clickable buttons. Each causes a sound to play,
fed to either the left or right audio channel through separate (planar)
arrays.
Planar audio can feed both channels at the same time from different arrays,
as well, but this example only uses one channel at a time for clarity. A
NULL array will supply silence for that channel.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,366 @@
/*
* This example code draws two clickable buttons. Each causes a sound to play,
* fed to either the left or right audio channel through separate ("planar")
* arrays.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_AudioStream *stream = NULL;
/* location of buttons on the screen. */
static const SDL_FRect rect_left_button = { 100, 170, 100, 100 };
static const SDL_FRect rect_right_button = { 440, 170, 100, 100 };
/* -1 if we're currently playing left, 1 if playing right, 0 if not playing. */
static int playing_sound = 0;
/* Raw audio data. These arrays are at the end of the source file. */
static const Uint8 left[1870];
static const Uint8 right[1777];
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
const SDL_AudioSpec spec = { SDL_AUDIO_U8, 2, 4000 }; /* Uint8 data, stereo, 4000Hz. */
SDL_SetAppMetadata("Example Audio Planar Data", "1.0", "com.example.audio-planar-data");
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/audio/planar-data", 640, 480, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
if (!stream) {
SDL_Log("Couldn't open audio device stream: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_ResumeAudioStreamDevice(stream); /* SDL_OpenAudioDeviceStream starts the device paused. Resume it! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
} else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (playing_sound == 0) { /* nothing currently playing? */
const SDL_FPoint point = { event->button.x, event->button.y };
if (SDL_PointInRectFloat(&point, &rect_left_button)) { /* clicked left button? */
const Uint8 *planes[] = { left, NULL }; /* specify NULL to say "this specific channel is silent" */
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, -1, SDL_arraysize(left));
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
playing_sound = -1; /* left is playing */
} else if (SDL_PointInRectFloat(&point, &rect_right_button)) { /* clicked right button? */
const Uint8 *planes[] = { NULL, right }; /* specify NULL to say "this specific channel is silent" */
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, -1, SDL_arraysize(right));
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
playing_sound = 1; /* right is playing */
}
}
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
static void render_button(const SDL_FRect *rect, const char *str, int button_value)
{
float x, y;
if (playing_sound == button_value) {
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); /* green while playing */
} else {
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); /* blue while not playing */
}
SDL_RenderFillRect(renderer, rect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
x = rect->x + ((rect->w - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(str))) / 2.0f);
y = rect->y + ((rect->h - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) / 2.0f);
SDL_RenderDebugText(renderer, x, y, str);
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
if (playing_sound) {
if (SDL_GetAudioStreamQueued(stream) == 0) { /* sound is done? We can play a new sound now. */
playing_sound = 0;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
render_button(&rect_left_button, "LEFT", -1);
render_button(&rect_right_button, "RIGHT", 1);
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyAudioStream(stream);
/* SDL will clean up the window/renderer for us. */
}
/* This is the audio data, as raw PCM samples (Uint8, 1 channel, 4000Hz) packed into C byte arrays for convenience. */
static const Uint8 left[1870] = {
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x80, 0x81, 0x82, 0x82,
0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7d,
0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x85, 0x84,
0x84, 0x83, 0x81, 0x7f, 0x7d, 0x7c, 0x7a, 0x7a, 0x7a, 0x77, 0x77, 0x77, 0x76, 0x76, 0x76, 0x77,
0x78, 0x7d, 0x82, 0x89, 0x8e, 0x92, 0x95, 0x95, 0x91, 0x8b, 0x84, 0x7d, 0x77, 0x73, 0x72, 0x72,
0x74, 0x75, 0x75, 0x75, 0x76, 0x74, 0x73, 0x73, 0x74, 0x79, 0x81, 0x89, 0x8f, 0x96, 0x9b, 0x9c,
0x98, 0x91, 0x88, 0x7e, 0x77, 0x74, 0x73, 0x74, 0x77, 0x7b, 0x7c, 0x7a, 0x77, 0x73, 0x6d, 0x69,
0x68, 0x6a, 0x73, 0x7f, 0x87, 0x8e, 0x99, 0xa1, 0x9e, 0x97, 0x90, 0x86, 0x7c, 0x76, 0x77, 0x7b,
0x80, 0x89, 0x91, 0x93, 0x91, 0x8e, 0x87, 0x7c, 0x71, 0x6b, 0x65, 0x60, 0x5d, 0x5f, 0x60, 0x61,
0x6b, 0x7b, 0x84, 0x8d, 0xa0, 0xae, 0xae, 0xa8, 0xa1, 0x94, 0x81, 0x73, 0x6f, 0x70, 0x74, 0x7e,
0x8d, 0x95, 0x97, 0x98, 0x92, 0x83, 0x72, 0x69, 0x61, 0x5a, 0x56, 0x59, 0x5d, 0x5f, 0x65, 0x75,
0x82, 0x87, 0x95, 0xaa, 0xb4, 0xb0, 0xaa, 0xa0, 0x8d, 0x77, 0x6c, 0x6c, 0x6d, 0x72, 0x81, 0x91,
0x98, 0x9a, 0x9a, 0x8f, 0x7a, 0x6a, 0x61, 0x58, 0x4f, 0x50, 0x57, 0x5b, 0x61, 0x74, 0x85, 0x8a,
0x96, 0xab, 0xb4, 0xae, 0xa5, 0x9c, 0x88, 0x71, 0x67, 0x69, 0x6c, 0x73, 0x85, 0x96, 0x9d, 0xa1,
0xa3, 0x96, 0x7f, 0x6e, 0x63, 0x56, 0x4c, 0x4d, 0x52, 0x53, 0x58, 0x6b, 0x80, 0x86, 0x92, 0xaa,
0xb8, 0xb4, 0xac, 0xa5, 0x90, 0x75, 0x69, 0x6a, 0x6c, 0x73, 0x86, 0x98, 0x9c, 0xa2, 0xa7, 0x99,
0x7f, 0x6e, 0x61, 0x54, 0x4c, 0x4b, 0x4d, 0x4f, 0x54, 0x66, 0x7c, 0x85, 0x90, 0xa9, 0xbc, 0xba,
0xb4, 0xac, 0x95, 0x78, 0x69, 0x67, 0x67, 0x71, 0x86, 0x99, 0x9d, 0xa4, 0xab, 0x9b, 0x7f, 0x6e,
0x5f, 0x50, 0x4b, 0x4e, 0x4e, 0x4e, 0x54, 0x60, 0x77, 0x86, 0x8e, 0xa4, 0xbb, 0xbf, 0xb9, 0xb3,
0x9e, 0x7d, 0x68, 0x65, 0x63, 0x6b, 0x84, 0x9a, 0x9d, 0xa3, 0xb0, 0x9f, 0x83, 0x71, 0x5f, 0x4d,
0x4c, 0x51, 0x51, 0x51, 0x56, 0x5a, 0x64, 0x7d, 0x90, 0x99, 0xad, 0xc3, 0xc2, 0xb5, 0xaa, 0x92,
0x71, 0x62, 0x65, 0x6a, 0x78, 0x92, 0xa2, 0xa1, 0xa7, 0xa8, 0x91, 0x78, 0x66, 0x55, 0x4a, 0x50,
0x54, 0x50, 0x50, 0x58, 0x5a, 0x65, 0x8b, 0x9b, 0x9b, 0xb7, 0xc9, 0xb3, 0xa6, 0xa2, 0x7d, 0x5a,
0x66, 0x6f, 0x70, 0x94, 0xa2, 0x90, 0x9b, 0xa5, 0x8f, 0x82, 0x77, 0x5c, 0x58, 0x60, 0x50, 0x46,
0x56, 0x49, 0x3a, 0x54, 0x97, 0xbe, 0xa9, 0xb0, 0xad, 0x91, 0xa7, 0xb3, 0x83, 0x6f, 0x6c, 0x5b,
0x71, 0x91, 0x9c, 0xac, 0x98, 0x78, 0x8a, 0xa6, 0xad, 0x9e, 0x72, 0x4d, 0x4e, 0x4f, 0x4e, 0x4a,
0x48, 0x46, 0x42, 0x4e, 0x99, 0xd5, 0xae, 0xb0, 0xb1, 0x8a, 0xb3, 0xbd, 0x82, 0x6b, 0x53, 0x56,
0x8b, 0x97, 0xa7, 0xaf, 0x74, 0x6b, 0x92, 0xaf, 0xc1, 0x8f, 0x55, 0x47, 0x4e, 0x60, 0x5e, 0x45,
0x4a, 0x4f, 0x3a, 0x44, 0x9f, 0xdf, 0xac, 0xa8, 0x93, 0x79, 0xbf, 0xc3, 0x92, 0x67, 0x36, 0x5a,
0x90, 0x9b, 0xb6, 0xa1, 0x6b, 0x68, 0x8d, 0xc3, 0xca, 0x83, 0x4f, 0x3d, 0x53, 0x72, 0x63, 0x46,
0x44, 0x55, 0x4f, 0x4c, 0x78, 0xcb, 0xbb, 0x93, 0x99, 0x79, 0xad, 0xd0, 0x9f, 0x70, 0x37, 0x4f,
0x90, 0x9e, 0xaf, 0x94, 0x73, 0x71, 0x89, 0xc0, 0xc0, 0x8f, 0x5b, 0x45, 0x62, 0x79, 0x6f, 0x5b,
0x46, 0x56, 0x54, 0x53, 0x59, 0x90, 0xd8, 0x95, 0x8c, 0x8c, 0x88, 0xd6, 0xb8, 0x83, 0x4c, 0x2f,
0x80, 0xa2, 0xaa, 0x9c, 0x69, 0x74, 0x80, 0xb0, 0xc6, 0x99, 0x78, 0x54, 0x69, 0x80, 0x7c, 0x69,
0x4b, 0x4e, 0x57, 0x4e, 0x4c, 0x5f, 0xae, 0xc3, 0x82, 0x86, 0x83, 0xac, 0xd9, 0xa3, 0x6a, 0x31,
0x50, 0xa0, 0xad, 0xa6, 0x6d, 0x59, 0x7f, 0x9e, 0xc8, 0xaf, 0x81, 0x74, 0x70, 0x8b, 0x83, 0x76,
0x58, 0x50, 0x56, 0x59, 0x58, 0x49, 0x62, 0x7c, 0xce, 0x99, 0x71, 0x9c, 0x8d, 0xd4, 0xb1, 0x6c,
0x4f, 0x37, 0x95, 0xab, 0x9b, 0x7f, 0x4b, 0x82, 0xa2, 0xba, 0xb5, 0x7b, 0x7d, 0x7d, 0x8d, 0x8b,
0x71, 0x62, 0x54, 0x5b, 0x4e, 0x5d, 0x4c, 0x5e, 0x57, 0x9c, 0xd4, 0x67, 0x94, 0x83, 0xa2, 0xd8,
0x83, 0x70, 0x2e, 0x59, 0xb5, 0x9d, 0xa1, 0x51, 0x55, 0x97, 0xad, 0xcb, 0x86, 0x77, 0x78, 0x95,
0xa1, 0x76, 0x6d, 0x58, 0x67, 0x5b, 0x4f, 0x66, 0x55, 0x67, 0x4e, 0x67, 0xd9, 0x88, 0x89, 0x86,
0x6f, 0xcd, 0x9b, 0x89, 0x4e, 0x39, 0x9f, 0xa0, 0xa9, 0x7a, 0x47, 0x88, 0x99, 0xbe, 0xac, 0x6b,
0x88, 0x87, 0xaf, 0x9a, 0x67, 0x71, 0x63, 0x74, 0x62, 0x55, 0x5c, 0x5e, 0x65, 0x5c, 0x54, 0xb1,
0xb0, 0x79, 0x8d, 0x6f, 0xac, 0xb7, 0x8e, 0x73, 0x44, 0x7b, 0xa1, 0x99, 0x90, 0x5a, 0x70, 0x97,
0xa0, 0xb4, 0x89, 0x83, 0x8e, 0x96, 0xa3, 0x7e, 0x6f, 0x6c, 0x6a, 0x6b, 0x5b, 0x5a, 0x61, 0x5e,
0x5d, 0x63, 0x66, 0xa0, 0xa6, 0x7c, 0x8d, 0x83, 0xa4, 0xad, 0x88, 0x7b, 0x58, 0x75, 0x95, 0x91,
0x92, 0x70, 0x75, 0x93, 0x9c, 0xab, 0x92, 0x84, 0x8d, 0x91, 0x96, 0x81, 0x70, 0x6b, 0x6c, 0x68,
0x62, 0x59, 0x5e, 0x69, 0x5a, 0x5a, 0x68, 0x5f, 0xa2, 0xb0, 0x6d, 0x87, 0x7e, 0xa0, 0xba, 0x89,
0x78, 0x53, 0x73, 0xa6, 0x9b, 0x95, 0x6c, 0x65, 0x8e, 0x9a, 0xab, 0x97, 0x7b, 0x85, 0x8e, 0x9a,
0x91, 0x71, 0x6b, 0x68, 0x65, 0x6e, 0x58, 0x5d, 0x70, 0x5d, 0x6d, 0x67, 0x5e, 0x80, 0x78, 0x94,
0x98, 0x7c, 0x96, 0x90, 0xa1, 0xa5, 0x82, 0x7f, 0x70, 0x7e, 0x94, 0x87, 0x87, 0x80, 0x88, 0x92,
0x8e, 0x96, 0x8c, 0x89, 0x84, 0x73, 0x72, 0x6f, 0x71, 0x6d, 0x5e, 0x61, 0x6a, 0x70, 0x77, 0x6f,
0x6d, 0x79, 0x76, 0x7f, 0x77, 0x75, 0x7e, 0x90, 0xa8, 0x8c, 0x85, 0x98, 0x9b, 0xa7, 0x93, 0x79,
0x78, 0x79, 0x91, 0x94, 0x87, 0x86, 0x85, 0x86, 0x8b, 0x89, 0x82, 0x7c, 0x74, 0x6d, 0x6c, 0x75,
0x75, 0x6f, 0x64, 0x69, 0x74, 0x7e, 0x83, 0x76, 0x75, 0x85, 0x8a, 0x89, 0x88, 0x78, 0x81, 0x88,
0x83, 0x85, 0x7e, 0x80, 0x88, 0x89, 0x8c, 0x8d, 0x8a, 0x8b, 0x88, 0x88, 0x89, 0x85, 0x81, 0x81,
0x7e, 0x7c, 0x7c, 0x77, 0x7d, 0x76, 0x6f, 0x7d, 0x7f, 0x78, 0x73, 0x76, 0x83, 0x84, 0x80, 0x7f,
0x82, 0x86, 0x80, 0x81, 0x83, 0x81, 0x81, 0x7e, 0x7d, 0x7b, 0x83, 0x8b, 0x85, 0x7a, 0x76, 0x83,
0x87, 0x82, 0x7d, 0x76, 0x7b, 0x80, 0x83, 0x81, 0x7a, 0x79, 0x7d, 0x82, 0x81, 0x82, 0x82, 0x83,
0x86, 0x80, 0x80, 0x81, 0x7e, 0x80, 0x7d, 0x7a, 0x7e, 0x81, 0x7e, 0x7e, 0x80, 0x7f, 0x81, 0x82,
0x80, 0x81, 0x82, 0x7f, 0x7f, 0x7d, 0x7c, 0x7f, 0x7b, 0x7b, 0x7d, 0x7a, 0x7a, 0x7e, 0x7e, 0x7c,
0x7c, 0x7f, 0x80, 0x7f, 0x80, 0x82, 0x81, 0x81, 0x80, 0x7e, 0x80, 0x7f, 0x81, 0x7b, 0x7c, 0x7f,
0x7f, 0x81, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x83, 0x7e, 0x7f, 0x85, 0x81, 0x83,
0x84, 0x80, 0x84, 0x81, 0x81, 0x83, 0x81, 0x83, 0x80, 0x84, 0x80, 0x80, 0x85, 0x80, 0x81, 0x7f,
0x82, 0x82, 0x81, 0x81, 0x80, 0x81, 0x80, 0x87, 0x81, 0x7c, 0x80, 0x7f, 0x80, 0x7d, 0x7c, 0x7d,
0x80, 0x80, 0x80, 0x82, 0x7d, 0x81, 0x82, 0x7e, 0x82, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x82,
0x7f, 0x80, 0x7f, 0x7f, 0x81, 0x7f, 0x80, 0x7e, 0x81, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x80, 0x80,
0x82, 0x7f, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x80,
0x80, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7d, 0x7e, 0x7d, 0x7c, 0x7d, 0x7c, 0x7c,
0x7d, 0x7c, 0x7d, 0x7e, 0x7f, 0x7e, 0x7e, 0x7f, 0x7d, 0x7f, 0x7f, 0x80, 0x7f, 0x7e, 0x7f, 0x80,
0x7e, 0x80, 0x7e, 0x7e, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x7e, 0x7d, 0x7f, 0x7d, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7e, 0x7f, 0x7f, 0x7d, 0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80,
0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f,
0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80,
0x81, 0x80, 0x82, 0x83, 0x81, 0x82, 0x81, 0x82, 0x82, 0x82, 0x81, 0x81, 0x83, 0x82, 0x82, 0x82,
0x81, 0x83, 0x82, 0x81, 0x81, 0x80, 0x80, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7e, 0x80, 0x7d, 0x80,
0x81, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x80, 0x81, 0x81, 0x80,
0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x81, 0x80, 0x7f, 0x81, 0x81, 0x82, 0x81,
0x80, 0x82, 0x82, 0x80, 0x81, 0x81, 0x80, 0x80, 0x7e, 0x7d, 0x7f, 0x7e, 0x81, 0x81, 0x7e, 0x7f,
0x82, 0x7f, 0x7d, 0x7f, 0x7d, 0x81, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80,
0x7f, 0x7e, 0x7f, 0x7f, 0x7e, 0x7c, 0x7d, 0x7e, 0x7d, 0x7d, 0x7e, 0x7d, 0x7e, 0x7c, 0x7e, 0x7e,
0x7c, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7d, 0x7d, 0x7c, 0x7b, 0x7c, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
0x7b, 0x7c, 0x7c, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x81,
0x81, 0x81, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
0x81, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f,
0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x81, 0x80, 0x83, 0x80, 0x80, 0x80, 0x84, 0x84,
0x7b, 0x7e, 0x80, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x81, 0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7e,
0x7f, 0x80, 0x80, 0x7f, 0x81, 0x82, 0x80, 0x80, 0x81, 0x81, 0x80, 0x81, 0x7f, 0x80, 0x80, 0x81,
0x81, 0x81, 0x81, 0x84, 0x83, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x81, 0x7e, 0x7e, 0x7f, 0x81, 0x7f,
0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x81, 0x82, 0x82, 0x80, 0x7f, 0x80,
0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x7d, 0x7e, 0x7e, 0x7f, 0x80,
0x80, 0x80, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x80, 0x80, 0x81, 0x7f, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7f,
0x7e, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x7e, 0x7f, 0x7f,
0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x7f, 0x80, 0x80, 0x82,
0x81, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x81, 0x80, 0x81, 0x80, 0x82, 0x7f,
0x7f, 0x7e, 0x7e, 0x80, 0x7e, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x81, 0x80,
0x81, 0x80, 0x80, 0x81, 0x80, 0x83, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7e, 0x80, 0x7f,
0x7f, 0x80, 0x7f, 0x82, 0x80, 0x81, 0x7f, 0x7e, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80,
0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x80, 0x80, 0x81, 0x81, 0x7f, 0x7f, 0x7f,
0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x81, 0x7f, 0x80, 0x7e, 0x7f, 0x7f,
0x7e, 0x80, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7d, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x80,
0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x81, 0x81, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f,
0x7f, 0x7f, 0x81, 0x81, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x7f,
0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x80, 0x80, 0x7f, 0x7e, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7e, 0x7f, 0x7e
};
static const Uint8 right[1777] = {
0x7f, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x82, 0x83, 0x83, 0x83,
0x82, 0x81, 0x81, 0x80, 0x7f, 0x7e, 0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x89, 0x89, 0x89, 0x88, 0x87, 0x84, 0x82, 0x80, 0x7e,
0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x76, 0x77, 0x78, 0x78, 0x78, 0x7b, 0x81, 0x87,
0x8c, 0x8e, 0x90, 0x92, 0x91, 0x8d, 0x87, 0x81, 0x7d, 0x7b, 0x7a, 0x79, 0x79, 0x7a, 0x79, 0x78,
0x75, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x76, 0x7b, 0x83, 0x88, 0x8b, 0x8f, 0x95, 0x98,
0x95, 0x8d, 0x86, 0x83, 0x80, 0x7e, 0x7c, 0x7c, 0x7e, 0x7e, 0x7c, 0x79, 0x78, 0x76, 0x75, 0x72,
0x73, 0x74, 0x72, 0x6f, 0x6d, 0x72, 0x7e, 0x87, 0x8b, 0x90, 0x98, 0x9f, 0x9b, 0x91, 0x85, 0x7f,
0x7b, 0x78, 0x79, 0x7f, 0x87, 0x8b, 0x8a, 0x89, 0x89, 0x86, 0x81, 0x79, 0x75, 0x74, 0x73, 0x73,
0x6f, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x72, 0x77, 0x82, 0x8f, 0x95, 0x99, 0x9c, 0x9e, 0x99, 0x8c,
0x7f, 0x74, 0x71, 0x70, 0x74, 0x7e, 0x8a, 0x92, 0x91, 0x8f, 0x8f, 0x8d, 0x85, 0x7c, 0x76, 0x75,
0x76, 0x75, 0x71, 0x6d, 0x6b, 0x68, 0x64, 0x64, 0x66, 0x6e, 0x83, 0x8f, 0x93, 0x9b, 0xa3, 0xa4,
0x97, 0x86, 0x76, 0x6f, 0x6d, 0x6e, 0x78, 0x87, 0x94, 0x98, 0x96, 0x94, 0x91, 0x89, 0x7e, 0x74,
0x6f, 0x70, 0x74, 0x72, 0x6e, 0x6b, 0x67, 0x62, 0x60, 0x60, 0x69, 0x84, 0x91, 0x95, 0xa1, 0xae,
0xb0, 0x9b, 0x84, 0x74, 0x6a, 0x65, 0x67, 0x78, 0x8b, 0x98, 0x9f, 0x9e, 0x9a, 0x90, 0x86, 0x7c,
0x71, 0x6a, 0x6c, 0x73, 0x74, 0x6d, 0x69, 0x65, 0x5e, 0x5c, 0x60, 0x6f, 0x8b, 0x95, 0x9b, 0xac,
0xb3, 0xa5, 0x89, 0x7a, 0x6b, 0x5c, 0x5f, 0x70, 0x88, 0x97, 0xa5, 0xac, 0xa1, 0x95, 0x8e, 0x86,
0x76, 0x6a, 0x6b, 0x72, 0x72, 0x6c, 0x67, 0x5e, 0x55, 0x52, 0x56, 0x78, 0x9c, 0x91, 0x9c, 0xbc,
0xb8, 0x98, 0x83, 0x7f, 0x5e, 0x4c, 0x6c, 0x83, 0x8a, 0x9a, 0xb7, 0xae, 0x8a, 0x8f, 0x93, 0x79,
0x69, 0x76, 0x76, 0x69, 0x70, 0x70, 0x5b, 0x50, 0x51, 0x57, 0x52, 0x77, 0xb2, 0x90, 0x95, 0xc8,
0xb1, 0x8d, 0x89, 0x8a, 0x55, 0x4e, 0x87, 0x7f, 0x82, 0xb3, 0xb9, 0x8f, 0x8c, 0x9d, 0x79, 0x71,
0x80, 0x6a, 0x61, 0x7b, 0x70, 0x51, 0x63, 0x62, 0x3e, 0x50, 0x61, 0x9a, 0xad, 0x7e, 0xba, 0xb5,
0x94, 0x9f, 0x93, 0x75, 0x4b, 0x7b, 0x79, 0x6c, 0xab, 0xaf, 0x9f, 0x93, 0x8e, 0x7a, 0x7f, 0x89,
0x6a, 0x6e, 0x71, 0x66, 0x5e, 0x63, 0x5c, 0x53, 0x53, 0x50, 0x5a, 0xb8, 0xbd, 0x6d, 0xc3, 0xb2,
0x8a, 0xa7, 0xa1, 0x70, 0x4c, 0x88, 0x63, 0x7d, 0xb1, 0xa1, 0xa6, 0x8e, 0x6a, 0x7c, 0x95, 0x8b,
0x84, 0x72, 0x5c, 0x5c, 0x67, 0x64, 0x61, 0x56, 0x65, 0x52, 0x44, 0x80, 0xda, 0x8a, 0x88, 0xc9,
0x89, 0x96, 0xb1, 0x92, 0x4a, 0x6f, 0x6d, 0x78, 0xa5, 0xa7, 0xa0, 0x98, 0x66, 0x6e, 0xa6, 0x9d,
0x95, 0x70, 0x52, 0x57, 0x73, 0x69, 0x72, 0x5a, 0x55, 0x52, 0x50, 0x3d, 0xb8, 0xdb, 0x5d, 0xa9,
0xab, 0x82, 0xad, 0xc3, 0x65, 0x4c, 0x6c, 0x6d, 0x98, 0xac, 0x9f, 0x97, 0x74, 0x5a, 0xa0, 0xb1,
0x9e, 0x7e, 0x52, 0x54, 0x74, 0x71, 0x6a, 0x6a, 0x5a, 0x53, 0x4b, 0x46, 0x5e, 0xe5, 0xaa, 0x62,
0xab, 0x8f, 0x97, 0xcb, 0xa5, 0x4b, 0x4f, 0x67, 0x88, 0xa6, 0xa4, 0x98, 0x84, 0x61, 0x80, 0xb7,
0xb4, 0x98, 0x64, 0x4e, 0x64, 0x77, 0x72, 0x72, 0x55, 0x54, 0x4e, 0x52, 0x3c, 0x96, 0xf0, 0x69,
0x7f, 0xa2, 0x80, 0xc1, 0xc8, 0x75, 0x46, 0x4d, 0x74, 0xa4, 0x9e, 0x95, 0x8a, 0x6a, 0x73, 0xa6,
0xb7, 0xb4, 0x81, 0x60, 0x5e, 0x71, 0x7c, 0x74, 0x6b, 0x54, 0x54, 0x48, 0x4f, 0x44, 0xc3, 0xcb,
0x5b, 0x9b, 0x86, 0x99, 0xd4, 0xa3, 0x71, 0x3e, 0x4b, 0x91, 0x99, 0x9d, 0x95, 0x70, 0x72, 0x85,
0xb0, 0xbd, 0xa5, 0x7e, 0x67, 0x67, 0x78, 0x77, 0x6e, 0x63, 0x53, 0x5b, 0x39, 0x50, 0x48, 0xb5,
0xc2, 0x6a, 0xa5, 0x77, 0xa8, 0xbd, 0x98, 0x89, 0x3a, 0x60, 0x83, 0x85, 0xa9, 0x87, 0x87, 0x74,
0x77, 0xac, 0xa9, 0xb9, 0x8a, 0x71, 0x6b, 0x6d, 0x81, 0x6d, 0x66, 0x51, 0x60, 0x3c, 0x50, 0x4a,
0x91, 0xbf, 0x83, 0xae, 0x7a, 0xa4, 0xa1, 0x97, 0x92, 0x4b, 0x73, 0x68, 0x86, 0x8e, 0x8c, 0x95,
0x79, 0x83, 0x86, 0xa2, 0xab, 0xa6, 0x8d, 0x79, 0x6a, 0x75, 0x68, 0x74, 0x56, 0x5c, 0x4e, 0x4c,
0x49, 0x5d, 0xb1, 0x88, 0xb9, 0x8d, 0xa4, 0x90, 0x94, 0x8b, 0x66, 0x72, 0x69, 0x83, 0x7c, 0x91,
0x82, 0x89, 0x79, 0x87, 0x8a, 0xa1, 0x9f, 0xa5, 0x95, 0x8d, 0x7a, 0x6f, 0x6f, 0x61, 0x62, 0x58,
0x5f, 0x52, 0x52, 0x4f, 0x80, 0x90, 0xa1, 0xa6, 0xa3, 0x9c, 0x90, 0x86, 0x74, 0x6d, 0x6c, 0x7a,
0x83, 0x8a, 0x8c, 0x88, 0x7f, 0x80, 0x82, 0x8f, 0x99, 0x9e, 0xa3, 0x9a, 0x93, 0x84, 0x73, 0x68,
0x5d, 0x5e, 0x5d, 0x5f, 0x5e, 0x5d, 0x52, 0x6a, 0x7d, 0x8d, 0x9f, 0xa6, 0xac, 0xa0, 0x95, 0x7d,
0x6e, 0x64, 0x6a, 0x76, 0x81, 0x8e, 0x98, 0x94, 0x8e, 0x84, 0x84, 0x84, 0x86, 0x91, 0x98, 0x9d,
0x9a, 0x8c, 0x7b, 0x67, 0x5c, 0x58, 0x58, 0x5e, 0x5e, 0x64, 0x60, 0x67, 0x75, 0x7f, 0x8e, 0x99,
0xa2, 0xa5, 0xa2, 0x99, 0x87, 0x74, 0x6a, 0x67, 0x6e, 0x7b, 0x87, 0x96, 0x97, 0x97, 0x94, 0x8e,
0x8c, 0x8a, 0x8b, 0x8a, 0x8a, 0x88, 0x84, 0x7b, 0x72, 0x66, 0x5e, 0x58, 0x57, 0x5a, 0x60, 0x64,
0x6c, 0x78, 0x81, 0x8c, 0x96, 0x9d, 0x9f, 0xa1, 0x99, 0x8f, 0x80, 0x76, 0x70, 0x6c, 0x70, 0x76,
0x81, 0x8a, 0x93, 0x97, 0x98, 0x94, 0x91, 0x8c, 0x8a, 0x87, 0x81, 0x7c, 0x74, 0x71, 0x6b, 0x68,
0x65, 0x62, 0x60, 0x61, 0x63, 0x67, 0x6c, 0x77, 0x82, 0x8a, 0x96, 0x9c, 0xa4, 0xa5, 0xa0, 0x95,
0x86, 0x7b, 0x71, 0x6e, 0x6e, 0x73, 0x79, 0x82, 0x8b, 0x94, 0x99, 0x98, 0x95, 0x8e, 0x88, 0x81,
0x7b, 0x77, 0x73, 0x6f, 0x6c, 0x6a, 0x68, 0x67, 0x66, 0x69, 0x69, 0x6e, 0x70, 0x77, 0x81, 0x88,
0x91, 0x97, 0x9f, 0xa1, 0xa2, 0x9b, 0x92, 0x82, 0x77, 0x6c, 0x6a, 0x6b, 0x71, 0x79, 0x83, 0x8d,
0x93, 0x97, 0x96, 0x95, 0x8f, 0x8b, 0x84, 0x7d, 0x76, 0x71, 0x6a, 0x68, 0x67, 0x68, 0x6b, 0x6d,
0x71, 0x73, 0x76, 0x79, 0x7e, 0x83, 0x8a, 0x8f, 0x94, 0x97, 0x97, 0x95, 0x8f, 0x87, 0x7f, 0x79,
0x76, 0x76, 0x78, 0x7a, 0x7e, 0x81, 0x86, 0x8a, 0x8c, 0x8e, 0x8d, 0x8a, 0x86, 0x80, 0x7c, 0x78,
0x74, 0x71, 0x70, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x82, 0x81, 0x80,
0x7e, 0x7f, 0x81, 0x84, 0x88, 0x8b, 0x8d, 0x8d, 0x8b, 0x87, 0x83, 0x7d, 0x7a, 0x77, 0x78, 0x7a,
0x7e, 0x81, 0x83, 0x84, 0x84, 0x84, 0x82, 0x80, 0x7f, 0x7d, 0x7b, 0x7a, 0x78, 0x78, 0x77, 0x78,
0x78, 0x79, 0x7c, 0x7e, 0x81, 0x83, 0x83, 0x84, 0x83, 0x82, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x80,
0x80, 0x81, 0x82, 0x83, 0x84, 0x84, 0x84, 0x83, 0x83, 0x81, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80,
0x7f, 0x7e, 0x7d, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x80, 0x80, 0x81, 0x80, 0x7f, 0x7e, 0x7d,
0x7d, 0x7d, 0x7e, 0x80, 0x80, 0x81, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x81, 0x80,
0x81, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x80, 0x80, 0x7e, 0x7d, 0x7d, 0x7e, 0x7e, 0x7f,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x80, 0x80, 0x80, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x82, 0x82, 0x82, 0x81, 0x80,
0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f,
0x80, 0x80, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f,
0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
0x81, 0x81, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x81, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e,
0x7e, 0x7d, 0x7e, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x82, 0x82, 0x81, 0x81, 0x80, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x80,
0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7f, 0x87, 0x83, 0x7d, 0x81, 0x80, 0x7e, 0x81, 0x7b,
0x7d, 0x84, 0x7f, 0x81, 0x83, 0x82, 0x7f, 0x80, 0x7c, 0x7b, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x7e, 0x7f, 0x7e, 0x7f, 0x80, 0x80, 0x81, 0x82, 0x82, 0x82, 0x82, 0x80, 0x80, 0x7f, 0x7f,
0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x82, 0x80, 0x7f, 0x80, 0x81, 0x80, 0x81, 0x7f,
0x83, 0x85, 0x7f, 0x80, 0x84, 0x83, 0x7d, 0x7c, 0x7d, 0x80, 0x7d, 0x7d, 0x7e, 0x7e, 0x7d, 0x83,
0x81, 0x7d, 0x7d, 0x81, 0x7f, 0x7c, 0x7c, 0x7c, 0x7d, 0x7c, 0x83, 0x80, 0x84, 0x84, 0x82, 0x7d,
0x7f, 0x7d, 0x7c, 0x7e, 0x7e, 0x7f, 0x81, 0x84, 0x82, 0x81, 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x80,
0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81,
0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x81, 0x83, 0x81, 0x82, 0x80, 0x80, 0x7f, 0x7f, 0x80,
0x7d, 0x80, 0x7e, 0x81, 0x7f, 0x81, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x81, 0x80, 0x82, 0x7f,
0x81, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x81, 0x7f, 0x81, 0x81, 0x81, 0x81, 0x81,
0x82, 0x81, 0x81, 0x80, 0x81, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7e,
0x7f, 0x7e, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x82, 0x80, 0x81, 0x81, 0x80,
0x81, 0x80, 0x81, 0x80, 0x81, 0x80, 0x81, 0x80, 0x80, 0x7e, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7f,
0x7f, 0x7f, 0x7e, 0x7d, 0x80, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x81, 0x7e, 0x81, 0x81, 0x83,
0x80, 0x81, 0x80, 0x80, 0x81, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x7f, 0x80, 0x7f, 0x80, 0x7d, 0x80,
0x7e, 0x7d, 0x80, 0x80, 0x83, 0x7f, 0x83, 0x7e, 0x83, 0x7f, 0x80, 0x7f, 0x7e, 0x81, 0x7f, 0x7f,
0x80, 0x80, 0x81, 0x7e, 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x83, 0x7f, 0x82, 0x7f, 0x82, 0x7f, 0x80,
0x80, 0x7e, 0x7f, 0x7d, 0x7e, 0x7d, 0x7e, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x81,
0x82, 0x80, 0x82, 0x80, 0x82, 0x80, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x80, 0x7e, 0x80, 0x80, 0x81,
0x7f, 0x7f, 0x7e, 0x80, 0x7d, 0x7e, 0x7e, 0x7f, 0x80, 0x7f, 0x80, 0x7e, 0x81, 0x7e, 0x81, 0x7f,
0x80, 0x7f, 0x80, 0x81, 0x7f, 0x80, 0x7e, 0x81, 0x7e, 0x80, 0x7d, 0x80, 0x80, 0x80, 0x81, 0x80,
0x82, 0x7e, 0x83, 0x7d, 0x80, 0x7c, 0x7d, 0x7e, 0x7c, 0x7e, 0x7d, 0x7e, 0x7f, 0x7e, 0x7e, 0x80,
0x7e, 0x81, 0x7e, 0x81, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x83, 0x80, 0x81, 0x80,
0x80, 0x80, 0x80, 0x7f, 0x80, 0x7e, 0x7f, 0x7f, 0x81, 0x7f, 0x80, 0x80, 0x7f, 0x7e, 0x80, 0x80,
0x81, 0x82, 0x81, 0x82, 0x81, 0x81, 0x81, 0x82, 0x80, 0x80, 0x7e, 0x82, 0x80, 0x84, 0x81, 0x80,
0x7f, 0x81, 0x80, 0x7f, 0x80, 0x7d, 0x80, 0x7d, 0x81, 0x7f, 0x81, 0x80, 0x81, 0x81, 0x80, 0x80,
0x7e, 0x80, 0x7f, 0x81, 0x7f, 0x81, 0x81, 0x81, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x81, 0x80, 0x80, 0x7e, 0x81, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x81,
0x7e, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80,
0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81,
0x80
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -27,7 +27,6 @@
typedef struct {
Uint8 ram[RAM_SIZE + 8];
Uint8 screenbuf[SCREEN_W * SCREEN_H];
Uint64 last_tick;
Uint64 tick_acc;
SDL_Window* window;
@@ -187,7 +186,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
}
if (!(vm->screen = SDL_CreateSurfaceFrom(
SCREEN_W, SCREEN_H, SDL_PIXELFORMAT_INDEX8, vm->screenbuf, SCREEN_W
SCREEN_W, SCREEN_H, SDL_PIXELFORMAT_INDEX8, vm->ram, SCREEN_W
))) {
return SDL_APP_FAILURE;
}
@@ -296,7 +295,6 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
SDL_UnlockTexture(vm->screentex);
SDL_RenderTexture(vm->renderer, vm->screentex, NULL, NULL);
}
if (vm->display_help) {
print(vm, 4, 4, "Drop a BytePusher file in this");
@@ -309,6 +307,7 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
vm->status_ticks -= 1;
print(vm, 4, SCREEN_H - 12, vm->status);
}
}
SDL_SetRenderTarget(vm->renderer, NULL);
SDL_RenderClear(vm->renderer);

View File

@@ -132,7 +132,7 @@ extern "C" {
#define SDL_TriggerBreakpoint() __debugbreak()
#elif defined(_MSC_VER) && defined(_M_IX86)
#define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
#elif defined(ANDROID)
#elif defined(ANDROID) || defined(__SYMBIAN32__)
#include <assert.h>
#define SDL_TriggerBreakpoint() assert(0)
#elif SDL_HAS_BUILTIN(__builtin_debugtrap)

View File

@@ -1021,7 +1021,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream);
/**
* Query an audio stream for its currently-bound device.
*
* This reports the audio device that an audio stream is currently bound to.
* This reports the logical audio device that an audio stream is currently
* bound to.
*
* If not bound, or invalid, this returns zero, which is not a valid device
* ID.
@@ -1063,6 +1064,17 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au
/**
* Get the properties associated with an audio stream.
*
* The application can hang any data it wants here, but the following
* properties are understood by SDL:
*
* - `SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN`: if true (the default), the
* stream be automatically cleaned up when the audio subsystem quits. If set
* to false, the streams will persist beyond that. This property is ignored
* for streams created through SDL_OpenAudioDeviceStream(), and will always
* be cleaned up. Streams that are not cleaned up will still be unbound from
* devices when the audio subsystem quits. This property was added in SDL
* 3.4.0.
*
* \param stream the SDL_AudioStream to query.
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
@@ -1073,6 +1085,9 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au
*/
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetAudioStreamProperties(SDL_AudioStream *stream);
#define SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN "SDL.audiostream.auto_cleanup"
/**
* Query the current format of an audio stream.
*
@@ -1149,14 +1164,14 @@ extern SDL_DECLSPEC float SDLCALL SDL_GetAudioStreamFrequencyRatio(SDL_AudioStre
*
* The frequency ratio is used to adjust the rate at which input data is
* consumed. Changing this effectively modifies the speed and pitch of the
* audio. A value greater than 1.0 will play the audio faster, and at a higher
* pitch. A value less than 1.0 will play the audio slower, and at a lower
* pitch.
* audio. A value greater than 1.0f will play the audio faster, and at a
* higher pitch. A value less than 1.0f will play the audio slower, and at a
* lower pitch. 1.0f means play at normal speed.
*
* This is applied during SDL_GetAudioStreamData, and can be continuously
* changed to create various effects.
*
* \param stream the stream the frequency ratio is being changed.
* \param stream the stream on which the frequency ratio is being changed.
* \param ratio the frequency ratio. 1.0 is normal speed. Must be between 0.01
* and 100.
* \returns true on success or false on failure; call SDL_GetError() for more
@@ -1332,7 +1347,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamInputChannelMap(SDL_AudioStre
* Channel maps are optional; most things do not need them, instead passing
* data in the [order that SDL expects](CategoryAudio#channel-layouts).
*
* The output channel map reorders data that leaving a stream via
* The output channel map reorders data that is leaving a stream via
* SDL_GetAudioStreamData.
*
* Each item in the array represents an input channel, and its value is the
@@ -1414,6 +1429,136 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamOutputChannelMap(SDL_AudioStr
*/
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len);
/**
* A callback that fires for completed SDL_PutAudioStreamDataNoCopy() data.
*
* When using SDL_PutAudioStreamDataNoCopy() to provide data to an
* SDL_AudioStream, it's not safe to dispose of the data until the stream has
* completely consumed it. Often times it's difficult to know exactly when
* this has happened.
*
* This callback fires once when the stream no longer needs the buffer,
* allowing the app to easily free or reuse it.
*
* \param userdata an opaque pointer provided by the app for their personal
* use.
* \param buf the pointer provided to SDL_PutAudioStreamDataNoCopy().
* \param buflen the size of buffer, in bytes, provided to
* SDL_PutAudioStreamDataNoCopy().
*
* \threadsafety This callbacks may run from any thread, so if you need to
* protect shared data, you should use SDL_LockAudioStream to
* serialize access; this lock will be held before your callback
* is called, so your callback does not need to manage the lock
* explicitly.
*
* \since This datatype is available since SDL 3.4.0.
*
* \sa SDL_SetAudioStreamGetCallback
* \sa SDL_SetAudioStreamPutCallback
*/
typedef void (SDLCALL *SDL_AudioStreamDataCompleteCallback)(void *userdata, const void *buf, int buflen);
/**
* Add external data to an audio stream without copying it.
*
* Unlike SDL_PutAudioStreamData(), this function does not make a copy of the
* provided data, instead storing the provided pointer. This means that the
* put operation does not need to allocate and copy the data, but the original
* data must remain available until the stream is done with it, either by
* being read from the stream in its entirety, or a call to
* SDL_ClearAudioStream() or SDL_DestroyAudioStream().
*
* The data must match the format/channels/samplerate specified in the latest
* call to SDL_SetAudioStreamFormat, or the format specified when creating the
* stream if it hasn't been changed.
*
* An optional callback may be provided, which is called when the stream no
* longer needs the data. Once this callback fires, the stream will not access
* the data again. This callback will fire for any reason the data is no
* longer needed, including clearing or destroying the stream.
*
* Note that there is still an allocation to store tracking information, so
* this function is more efficient for larger blocks of data. If you're
* planning to put a few samples at a time, it will be more efficient to use
* SDL_PutAudioStreamData(), which allocates and buffers in blocks.
*
* \param stream the stream the audio data is being added to.
* \param buf a pointer to the audio data to add.
* \param len the number of bytes to add to the stream.
* \param callback the callback function to call when the data is no longer
* needed by the stream. May be NULL.
* \param userdata an opaque pointer provided to the callback for its own
* personal use.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety It is safe to call this function from any thread, but if the
* stream has a callback set, the caller might need to manage
* extra locking.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_ClearAudioStream
* \sa SDL_FlushAudioStream
* \sa SDL_GetAudioStreamData
* \sa SDL_GetAudioStreamQueued
*/
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamDataNoCopy(SDL_AudioStream *stream, const void *buf, int len, SDL_AudioStreamDataCompleteCallback callback, void *userdata);
/**
* Add data to the stream with each channel in a separate array.
*
* This data must match the format/channels/samplerate specified in the latest
* call to SDL_SetAudioStreamFormat, or the format specified when creating the
* stream if it hasn't been changed.
*
* The data will be interleaved and queued. Note that SDL_AudioStream only
* operates on interleaved data, so this is simply a convenience function for
* easily queueing data from sources that provide separate arrays. There is no
* equivalent function to retrieve planar data.
*
* The arrays in `channel_buffers` are ordered as they are to be interleaved;
* the first array will be the first sample in the interleaved data. Any
* individual array may be NULL; in this case, silence will be interleaved for
* that channel.
*
* `num_channels` specifies how many arrays are in `channel_buffers`. This can
* be used as a safety to prevent overflow, in case the stream format has
* changed elsewhere. If more channels are specified than the current input
* spec, they are ignored. If less channels are specified, the missing arrays
* are treated as if they are NULL (silence is written to those channels). If
* the count is -1, SDL will assume the array count matches the current input
* spec.
*
* Note that `num_samples` is the number of _samples per array_. This can also
* be thought of as the number of _sample frames_ to be queued. A value of 1
* with stereo arrays will queue two samples to the stream. This is different
* than SDL_PutAudioStreamData, which wants the size of a single array in
* bytes.
*
* \param stream the stream the audio data is being added to.
* \param channel_buffers a pointer to an array of arrays, one array per
* channel.
* \param num_channels the number of arrays in `channel_buffers` or -1.
* \param num_samples the number of _samples_ per array to write to the
* stream.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety It is safe to call this function from any thread, but if the
* stream has a callback set, the caller might need to manage
* extra locking.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_ClearAudioStream
* \sa SDL_FlushAudioStream
* \sa SDL_GetAudioStreamData
* \sa SDL_GetAudioStreamQueued
*/
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_channels, int num_samples);
/**
* Get converted/resampled data from the stream.
*
@@ -1583,8 +1728,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioStreamDevice(SDL_AudioStream *str
* previously been paused. Once unpaused, any bound audio streams will begin
* to progress again, and audio can be generated.
*
* Remember, SDL_OpenAudioDeviceStream opens device in a paused state, so this
* function call is required for audio playback to begin on such device.
* SDL_OpenAudioDeviceStream opens audio devices in a paused state, so this
* function call is required for audio playback to begin on such devices.
*
* \param stream the audio stream associated with the audio device to resume.
* \returns true on success or false on failure; call SDL_GetError() for more
@@ -1841,7 +1986,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream)
* Also unlike other functions, the audio device begins paused. This is to map
* more closely to SDL2-style behavior, since there is no extra step here to
* bind a stream to begin audio flowing. The audio device should be resumed
* with `SDL_ResumeAudioStreamDevice(stream);`
* with SDL_ResumeAudioStreamDevice().
*
* This function works with both playback and recording devices.
*
@@ -1887,6 +2032,85 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream)
*/
extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec, SDL_AudioStreamCallback callback, void *userdata);
/**
* A callback that fires around an audio device's processing work.
*
* This callback fires when a logical audio device is about to start accessing
* its bound audio streams, and fires again when it has finished accessing
* them. It covers the range of one "iteration" of the audio device.
*
* It can be useful to use this callback to update state that must apply to
* all bound audio streams atomically: to make sure state changes don't happen
* while half of the streams are already processed for the latest audio
* buffer.
*
* This callback should run as quickly as possible and not block for any
* significant time, as this callback delays submission of data to the audio
* device, which can cause audio playback problems. This callback delays all
* audio processing across a single physical audio device: all its logical
* devices and all bound audio streams. Use it carefully.
*
* \param userdata a pointer provided by the app through
* SDL_SetAudioPostmixCallback, for its own use.
* \param devid the audio device this callback is running for.
* \param start true if this is the start of the iteration, false if the end.
*
* \threadsafety This will run from a background thread owned by SDL. The
* application is responsible for locking resources the callback
* touches that need to be protected.
*
* \since This datatype is available since SDL 3.4.0.
*
* \sa SDL_SetAudioIterationCallbacks
*/
typedef void (SDLCALL *SDL_AudioIterationCallback)(void *userdata, SDL_AudioDeviceID devid, bool start);
/**
* Set callbacks that fire around a new iteration of audio device processing.
*
* Two callbacks are provided here: one that runs when a device is about to
* process its bound audio streams, and another that runs when the device has
* finished processing them.
*
* These callbacks can run at any time, and from any thread; if you need to
* serialize access to your app's data, you should provide and use a mutex or
* other synchronization device.
*
* Generally these callbacks are used to apply state that applies to multiple
* bound audio streams, with a guarantee that the audio device's thread isn't
* halfway through processing them. Generally a finer-grained lock through
* SDL_LockAudioStream() is more appropriate.
*
* The callbacks are extremely time-sensitive; the callback should do the
* least amount of work possible and return as quickly as it can. The longer
* the callback runs, the higher the risk of audio dropouts or other problems.
*
* This function will block until the audio device is in between iterations,
* so any existing callback that might be running will finish before this
* function sets the new callback and returns.
*
* Physical devices do not accept these callbacks, only logical devices
* created through SDL_OpenAudioDevice() can be.
*
* Setting a NULL callback function disables any previously-set callback.
* Either callback may be NULL, and the same callback is permitted to be used
* for both.
*
* \param devid the ID of an opened audio device.
* \param start a callback function to be called at the start of an iteration.
* Can be NULL.
* \param end a callback function to be called at the end of an iteration. Can
* be NULL.
* \param userdata app-controlled pointer passed to callback. Can be NULL.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.4.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioIterationCallbacks(SDL_AudioDeviceID devid, SDL_AudioIterationCallback start, SDL_AudioIterationCallback end, void *userdata);
/**
* A callback that fires when data is about to be fed to an audio device.
*

View File

@@ -261,9 +261,9 @@
*
* On compilers without restrict support, this is defined to nothing.
*
* \since This macro is available since SDL 3.2.0.
* \since This macro is available since SDL 3.4.0.
*/
#define SDL_RESTRICT __restrict__
#define SDL_RESTRICT __restrict
/**
* Check if the compiler supports a given builtin functionality.
@@ -281,9 +281,61 @@
*/
#define SDL_HAS_BUILTIN(x) __has_builtin(x)
/**
* A macro to specify data alignment.
*
* This informs the compiler that a given datatype or variable must be aligned
* to a specific byte count.
*
* For example:
*
* ```c
* // make sure this is struct is aligned to 16 bytes for SIMD access.
* typedef struct {
* float x, y, z, w;
* } SDL_ALIGNED(16) MySIMDAlignedData;
*
* // make sure this one field in a struct is aligned to 16 bytes for SIMD access.
* typedef struct {
* SomeStuff stuff;
* float position[4] SDL_ALIGNED(16);
* SomeOtherStuff other_stuff;
* } MyStruct;
*
* // make sure this variable is aligned to 32 bytes.
* int SDL_ALIGNED(32) myval = 0;
* ```
*
* Alignment is only guaranteed for things the compiler places: local
* variables on the stack and global/static variables. To dynamically allocate
* something that respects this alignment, use SDL_aligned_alloc() or some
* other mechanism.
*
* On compilers without alignment support, this macro is defined to an invalid
* symbol, to make it clear that the current compiler is likely to generate
* incorrect code when it sees this macro.
*
* \param x the byte count to align to, so the data's address will be a
* multiple of this value.
*
* \since This macro is available since SDL 3.4.0.
*/
#define SDL_ALIGNED(x) __attribute__((aligned(x)))
/* end of wiki documentation section. */
#endif
/* `restrict` is from C99, but __restrict works with both Visual Studio and GCC. */
#ifndef SDL_RESTRICT
# if defined(restrict) || ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)))
# define SDL_RESTRICT restrict
# elif defined(_MSC_VER) || defined(__GNUC__) || defined(__clang__)
# define SDL_RESTRICT __restrict
# else
# define SDL_RESTRICT
# endif
#endif
#ifndef SDL_HAS_BUILTIN
#ifdef __has_builtin
#define SDL_HAS_BUILTIN(x) __has_builtin(x)
@@ -389,7 +441,7 @@
#endif /* SDL_FORCE_INLINE not defined */
#ifndef SDL_NORETURN
#ifdef __GNUC__
#if defined(__GNUC__)
#define SDL_NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER)
#define SDL_NORETURN __declspec(noreturn)
@@ -484,3 +536,18 @@
#define SDL_ALLOC_SIZE2(p1, p2)
#endif
#endif /* SDL_ALLOC_SIZE2 not defined */
#ifndef SDL_ALIGNED
#if defined(__clang__) || defined(__GNUC__)
#define SDL_ALIGNED(x) __attribute__((aligned(x)))
#elif defined(_MSC_VER)
#define SDL_ALIGNED(x) __declspec(align(x))
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
#define SDL_ALIGNED(x) alignas(x)
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#define SDL_ALIGNED(x) _Alignas(x)
#else
#define SDL_ALIGNED(x) PLEASE_DEFINE_SDL_ALIGNED
#endif
#endif /* SDL_ALIGNED not defined */

View File

@@ -135,7 +135,8 @@ typedef enum SDL_EventType
/* 0x201 was SDL_SYSWMEVENT, reserve the number for sdl2-compat */
SDL_EVENT_WINDOW_SHOWN = 0x202, /**< Window has been shown */
SDL_EVENT_WINDOW_HIDDEN, /**< Window has been hidden */
SDL_EVENT_WINDOW_EXPOSED, /**< Window has been exposed and should be redrawn, and can be redrawn directly from event watchers for this event */
SDL_EVENT_WINDOW_EXPOSED, /**< Window has been exposed and should be redrawn, and can be redrawn directly from event watchers for this event.
data1 is 1 for live-resize expose events, 0 otherwise. */
SDL_EVENT_WINDOW_MOVED, /**< Window has been moved to data1, data2 */
SDL_EVENT_WINDOW_RESIZED, /**< Window has been resized to data1xdata2 */
SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED,/**< The pixel size of the window has changed to data1xdata2 */
@@ -492,6 +493,8 @@ typedef struct SDL_MouseWheelEvent
SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
float mouse_x; /**< X coordinate, relative to window */
float mouse_y; /**< Y coordinate, relative to window */
Sint32 integer_x; /**< The amount scrolled horizontally, accumulated to whole scroll "ticks" (added in 3.2.12) */
Sint32 integer_y; /**< The amount scrolled vertically, accumulated to whole scroll "ticks" (added in 3.2.12) */
} SDL_MouseWheelEvent;
/**
@@ -779,7 +782,7 @@ typedef struct SDL_TouchFingerEvent
} SDL_TouchFingerEvent;
/**
* Pressure-sensitive pen proximity event structure (event.pmotion.*)
* Pressure-sensitive pen proximity event structure (event.pproximity.*)
*
* When a pen becomes visible to the system (it is close enough to a tablet,
* etc), SDL will send an SDL_EVENT_PEN_PROXIMITY_IN event with the new pen's
@@ -1565,6 +1568,38 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents);
*/
extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromEvent(const SDL_Event *event);
/**
* Generate a human-readable description of an event.
*
* This will fill `buf` with a null-terminated string that might look
* something like this:
*
* ```
* SDL_EVENT_MOUSE_MOTION (timestamp=1140256324 windowid=2 which=0 state=0 x=492.99 y=139.09 xrel=52 yrel=6)
* ```
*
* The exact format of the string is not guaranteed; it is intended for
* logging purposes, to be read by a human, and not parsed by a computer.
*
* The returned value follows the same rules as SDL_snprintf(): `buf` will
* always be NULL-terminated (unless `buflen` is zero), and will be truncated
* if `buflen` is too small. The return code is the number of bytes needed for
* the complete string, not counting the NULL-terminator, whether the string
* was truncated or not. Unlike SDL_snprintf(), though, this function never
* returns -1.
*
* \param event an event to describe. May be NULL.
* \param buf the buffer to fill with the description string. May be NULL.
* \param buflen the maximum bytes that can be written to `buf`.
* \returns number of bytes needed for the full string, not counting the
* null-terminator byte.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.4.0.
*/
extern SDL_DECLSPEC int SDLCALL SDL_GetEventDescription(const SDL_Event *event, char *buf, int buflen);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}

View File

@@ -444,10 +444,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetPathInfo(const char *path, SDL_PathInfo
* Enumerate a directory tree, filtered by pattern, and return a list.
*
* Files are filtered out if they don't match the string in `pattern`, which
* may contain wildcard characters '\*' (match everything) and '?' (match one
* may contain wildcard characters `*` (match everything) and `?` (match one
* character). If pattern is NULL, no filtering is done and all results are
* returned. Subdirectories are permitted, and are specified with a path
* separator of '/'. Wildcard characters '\*' and '?' never match a path
* separator of `/`. Wildcard characters `*` and `?` never match a path
* separator.
*
* `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching

View File

@@ -118,6 +118,7 @@ typedef enum SDL_GamepadType
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT,
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT,
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR,
SDL_GAMEPAD_TYPE_GAMECUBE,
SDL_GAMEPAD_TYPE_COUNT
} SDL_GamepadType;
@@ -127,8 +128,9 @@ typedef enum SDL_GamepadType
* For controllers that use a diamond pattern for the face buttons, the
* south/east/west/north buttons below correspond to the locations in the
* diamond pattern. For Xbox controllers, this would be A/B/X/Y, for Nintendo
* Switch controllers, this would be B/A/Y/X, for PlayStation controllers this
* would be Cross/Circle/Square/Triangle.
* Switch controllers, this would be B/A/Y/X, for GameCube controllers this
* would be A/X/B/Y, for PlayStation controllers this would be
* Cross/Circle/Square/Triangle.
*
* For controllers that don't use a diamond pattern for the face buttons, the
* south/east/west/north buttons indicate the buttons labeled A, B, C, D, or

View File

@@ -206,14 +206,20 @@
* underlying graphics API. While it's possible that we have done something
* inefficiently, it's very unlikely especially if you are relatively
* inexperienced with GPU rendering. Please see the performance tips above and
* make sure you are following them. Additionally, tools like RenderDoc can be
* very helpful for diagnosing incorrect behavior and performance issues.
* make sure you are following them. Additionally, tools like
* [RenderDoc](https://renderdoc.org/)
* can be very helpful for diagnosing incorrect behavior and performance
* issues.
*
* ## System Requirements
*
* **Vulkan:** Supported on Windows, Linux, Nintendo Switch, and certain
* Android devices. Requires Vulkan 1.0 with the following extensions and
* device features:
* ### Vulkan
*
* SDL driver name: "vulkan" (for use in SDL_CreateGPUDevice() and
* SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING)
*
* Supported on Windows, Linux, Nintendo Switch, and certain Android devices.
* Requires Vulkan 1.0 with the following extensions and device features:
*
* - `VK_KHR_swapchain`
* - `VK_KHR_maintenance1`
@@ -224,12 +230,19 @@
* - `drawIndirectFirstInstance`
* - `sampleRateShading`
*
* **D3D12:** Supported on Windows 10 or newer, Xbox One (GDK), and Xbox
* Series X|S (GDK). Requires a GPU that supports DirectX 12 Feature Level
* 11_1.
* ### D3D12
*
* **Metal:** Supported on macOS 10.14+ and iOS/tvOS 13.0+. Hardware
* requirements vary by operating system:
* SDL driver name: "direct3d12"
*
* Supported on Windows 10 or newer, Xbox One (GDK), and Xbox Series X|S
* (GDK). Requires a GPU that supports DirectX 12 Feature Level 11_1.
*
* ### Metal
*
* SDL driver name: "metal"
*
* Supported on macOS 10.14+ and iOS/tvOS 13.0+. Hardware requirements vary by
* operating system:
*
* - macOS requires an Apple Silicon or
* [Intel Mac2 family](https://developer.apple.com/documentation/metal/mtlfeatureset/mtlfeatureset_macos_gpufamily2_v1?language=objc)
@@ -237,6 +250,26 @@
* - iOS/tvOS requires an A9 GPU or newer
* - iOS Simulator and tvOS Simulator are unsupported
*
* ## Coordinate System
*
* The GPU API uses a left-handed coordinate system, following the convention
* of D3D12 and Metal. Specifically:
*
* - **Normalized Device Coordinates:** The lower-left corner has an x,y
* coordinate of `(-1.0, -1.0)`. The upper-right corner is `(1.0, 1.0)`. Z
* values range from `[0.0, 1.0]` where 0 is the near plane.
* - **Viewport Coordinates:** The top-left corner has an x,y coordinate of
* `(0, 0)` and extends to the bottom-right corner at `(viewportWidth,
* viewportHeight)`. +Y is down.
* - **Texture Coordinates:** The top-left corner has an x,y coordinate of
* `(0, 0)` and extends to the bottom-right corner at `(1.0, 1.0)`. +Y is
* down.
*
* If the backend driver differs from this convention (e.g. Vulkan, which has
* an NDC that assumes +Y is down), SDL will automatically convert the
* coordinate system behind the scenes, so you don't need to perform any
* coordinate flipping logic in your shaders.
*
* ## Uniform Data
*
* Uniforms are for passing data to shaders. The uniform data will be constant
@@ -302,6 +335,39 @@
* unreferenced data in a bound resource without cycling, but overwriting a
* section of data that has already been referenced will produce unexpected
* results.
*
* ## Debugging
*
* At some point of your GPU journey, you will probably encounter issues that
* are not traceable with regular debugger - for example, your code compiles
* but you get an empty screen, or your shader fails in runtime.
*
* For debugging such cases, there are tools that allow visually inspecting
* the whole GPU frame, every drawcall, every bound resource, memory buffers,
* etc. They are the following, per platform:
*
* * For Windows/Linux, use
* [RenderDoc](https://renderdoc.org/)
* * For MacOS (Metal), use Xcode built-in debugger (Open XCode, go to Debug >
* Debug Executable..., select your application, set "GPU Frame Capture" to
* "Metal" in scheme "Options" window, run your app, and click the small
* Metal icon on the bottom to capture a frame)
*
* Aside from that, you may want to enable additional debug layers to receive
* more detailed error messages, based on your GPU backend:
*
* * For D3D12, the debug layer is an optional feature that can be installed
* via "Windows Settings -> System -> Optional features" and adding the
* "Graphics Tools" optional feature.
* * For Vulkan, you will need to install Vulkan SDK on Windows, and on Linux,
* you usually have some sort of `vulkan-validation-layers` system package
* that should be installed.
* * For Metal, it should be enough just to run the application from XCode to
* receive detailed errors or warnings in the output.
*
* Don't hesitate to use tools as RenderDoc when encountering runtime issues
* or unexpected output on screen, quick GPU frame inspection can usually help
* you fix the majority of such problems.
*/
#ifndef SDL_gpu_h_
@@ -1312,10 +1378,15 @@ typedef struct SDL_GPUViewport
* texture.
*
* If either of `pixels_per_row` or `rows_per_layer` is zero, then width and
* height of passed SDL_GPUTextureRegion to SDL_UploadToGPUTexture
* height of passed SDL_GPUTextureRegion to SDL_UploadToGPUTexture or
* SDL_DownloadFromGPUTexture are used as default values respectively and data
* is considered to be tightly packed.
*
* / SDL_DownloadFromGPUTexture are used as default values respectively and
* data is considered to be tightly packed.
* **WARNING**: Direct3D 12 requires texture data row pitch to be 256 byte
* aligned, and offsets to be aligned to 512 bytes. If they are not, SDL will
* make a temporary copy of the data that is properly aligned, but this adds
* overhead to the transfer process. Apps can avoid this by aligning their
* data appropriately, or using a different GPU backend than Direct3D 12.
*
* \since This struct is available since SDL 3.2.0.
*
@@ -1620,6 +1691,9 @@ typedef struct SDL_GPUStencilOpState
* \since This struct is available since SDL 3.2.0.
*
* \sa SDL_GPUColorTargetDescription
* \sa SDL_GPUBlendFactor
* \sa SDL_GPUBlendOp
* \sa SDL_GPUColorComponentFlags
*/
typedef struct SDL_GPUColorTargetBlendState
{
@@ -1643,6 +1717,8 @@ typedef struct SDL_GPUColorTargetBlendState
* \since This struct is available since SDL 3.2.0.
*
* \sa SDL_CreateGPUShader
* \sa SDL_GPUShaderFormat
* \sa SDL_GPUShaderStage
*/
typedef struct SDL_GPUShaderCreateInfo
{
@@ -2118,6 +2194,13 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsProperties(
/**
* Creates a GPU context.
*
* The GPU driver name can be one of the following:
*
* - "vulkan": [Vulkan](CategoryGPU#vulkan)
* - "direct3d12": [D3D12](CategoryGPU#d3d12)
* - "metal": [Metal](CategoryGPU#metal)
* - NULL: let SDL pick the optimal driver
*
* \param format_flags a bitflag indicating which shader formats the app is
* able to provide.
* \param debug_mode enable debug mode properties and validations.
@@ -2128,6 +2211,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsProperties(
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_CreateGPUDeviceWithProperties
* \sa SDL_GetGPUShaderFormats
* \sa SDL_GetGPUDeviceDriver
* \sa SDL_DestroyGPUDevice
@@ -2172,6 +2256,25 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice(
* - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING`: the prefix to
* use for all vertex semantics, default is "TEXCOORD".
*
* With the Vulkan renderer:
*
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN`: Enable
* device feature shaderClipDistance. If disabled, clip distances are not
* supported in shader code: gl_ClipDistance[] built-ins of GLSL,
* SV_ClipDistance0/1 semantics of HLSL and [[clip_distance]] attribute of
* Metal. Defaults to true.
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN`: Enable device
* feature depthClamp. If disabled, there is no depth clamp support and
* enable_depth_clip in SDL_GPURasterizerState must always be set to true.
* Defaults to true.
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN`: Enable
* device feature drawIndirectFirstInstance. If disabled, the argument
* first_instance of SDL_GPUIndirectDrawCommand must be set to zero.
* Defaults to true.
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN`: Enable
* device feature samplerAnisotropy. If disabled, enable_anisotropy of
* SDL_GPUSamplerCreateInfo must be set to false. Defaults to true.
*
* \param props the properties to use.
* \returns a GPU context on success or NULL on failure; call SDL_GetError()
* for more information.
@@ -2197,6 +2300,10 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN "SDL.gpu.device.create.shaders.msl"
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib"
#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic"
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN "SDL.gpu.device.create.vulkan.shaderclipdistance"
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN "SDL.gpu.device.create.vulkan.depthclamp"
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN "SDL.gpu.device.create.vulkan.drawindirectfirstinstance"
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN "SDL.gpu.device.create.vulkan.sampleranisotropy"
/**
* Destroys a GPU context previously returned by SDL_CreateGPUDevice.
@@ -2587,9 +2694,9 @@ extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader(
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT`: (Direct3D 12 only)
* if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, clear
* the texture to a depth of this value. Defaults to zero.
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8`: (Direct3D 12
* - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER`: (Direct3D 12
* only) if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET,
* clear the texture to a stencil of this value. Defaults to zero.
* clear the texture to a stencil of this Uint8 value. Defaults to zero.
* - `SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING`: a name that can be displayed
* in debugging tools.
*
@@ -2620,7 +2727,7 @@ extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL SDL_CreateGPUTexture(
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 "SDL.gpu.texture.create.d3d12.clear.stencil"
#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER "SDL.gpu.texture.create.d3d12.clear.stencil"
#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name"
/**
@@ -2942,6 +3049,9 @@ extern SDL_DECLSPEC SDL_GPUCommandBuffer * SDLCALL SDL_AcquireGPUCommandBuffer(
* terms this means you must ensure that vec3 and vec4 fields are 16-byte
* aligned.
*
* For detailed information about accessing uniform data from a shader, please
* refer to SDL_CreateGPUShader.
*
* \param command_buffer a command buffer.
* \param slot_index the vertex uniform slot to push data to.
* \param data client data to write.
@@ -3895,7 +4005,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseWindowFromGPUDevice(
* supported via SDL_WindowSupportsGPUPresentMode /
* SDL_WindowSupportsGPUSwapchainComposition prior to calling this function.
*
* SDL_GPU_PRESENTMODE_VSYNC and SDL_GPU_SWAPCHAINCOMPOSITION_SDR are always
* SDL_GPU_PRESENTMODE_VSYNC with SDL_GPU_SWAPCHAINCOMPOSITION_SDR is always
* supported.
*
* \param device a GPU context.
@@ -3969,7 +4079,9 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma
* buffer used to acquire it.
*
* This function will fill the swapchain texture handle with NULL if too many
* frames are in flight. This is not an error.
* frames are in flight. This is not an error. This NULL pointer should not be
* passed back into SDL. Instead, it should be considered as an indication to
* wait until the swapchain is available.
*
* If you use this function, it is possible to create a situation where many
* command buffers are allocated while the rendering context waits for the GPU

View File

@@ -70,7 +70,7 @@
* {
* SDL_Haptic *haptic;
* SDL_HapticEffect effect;
* int effect_id;
* SDL_HapticEffectID effect_id;
*
* // Open the device
* haptic = SDL_OpenHapticFromJoystick(joystick);
@@ -149,6 +149,19 @@ extern "C" {
*/
typedef struct SDL_Haptic SDL_Haptic;
/*
* Misc defines.
*/
/**
* Used to play a device an infinite number of times.
*
* \since This macro is available since SDL 3.2.0.
*
* \sa SDL_RunHapticEffect
*/
#define SDL_HAPTIC_INFINITY 4294967295U
/**
* \name Haptic features
@@ -162,6 +175,11 @@ typedef struct SDL_Haptic SDL_Haptic;
*/
/* @{ */
/**
* Type of haptic effect.
*/
typedef Uint16 SDL_HapticEffectType;
/**
* Constant effect supported.
*
@@ -383,6 +401,11 @@ typedef struct SDL_Haptic SDL_Haptic;
*/
/* @{ */
/**
* Type of coordinates used for haptic direction.
*/
typedef Uint8 SDL_HapticDirectionType;
/**
* Uses polar coordinates for the direction.
*
@@ -426,18 +449,15 @@ typedef struct SDL_Haptic SDL_Haptic;
/* @} *//* Haptic features */
/*
* Misc defines.
*/
/**
* Used to play a device an infinite number of times.
* ID for haptic effects.
*
* \since This macro is available since SDL 3.2.0.
* This is -1 if the ID is invalid.
*
* \sa SDL_RunHapticEffect
* \sa SDL_CreateHapticEffect
*/
#define SDL_HAPTIC_INFINITY 4294967295U
typedef int SDL_HapticEffectID;
/**
@@ -545,7 +565,7 @@ typedef struct SDL_Haptic SDL_Haptic;
*/
typedef struct SDL_HapticDirection
{
Uint8 type; /**< The type of encoding. */
SDL_HapticDirectionType type; /**< The type of encoding. */
Sint32 dir[3]; /**< The encoded direction. */
} SDL_HapticDirection;
@@ -566,7 +586,7 @@ typedef struct SDL_HapticDirection
typedef struct SDL_HapticConstant
{
/* Header */
Uint16 type; /**< SDL_HAPTIC_CONSTANT */
SDL_HapticEffectType type; /**< SDL_HAPTIC_CONSTANT */
SDL_HapticDirection direction; /**< Direction of the effect. */
/* Replay */
@@ -652,7 +672,7 @@ typedef struct SDL_HapticConstant
typedef struct SDL_HapticPeriodic
{
/* Header */
Uint16 type; /**< SDL_HAPTIC_SINE, SDL_HAPTIC_SQUARE
SDL_HapticEffectType type; /**< SDL_HAPTIC_SINE, SDL_HAPTIC_SQUARE
SDL_HAPTIC_TRIANGLE, SDL_HAPTIC_SAWTOOTHUP or
SDL_HAPTIC_SAWTOOTHDOWN */
SDL_HapticDirection direction; /**< Direction of the effect. */
@@ -708,7 +728,7 @@ typedef struct SDL_HapticPeriodic
typedef struct SDL_HapticCondition
{
/* Header */
Uint16 type; /**< SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER,
SDL_HapticEffectType type; /**< SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER,
SDL_HAPTIC_INERTIA or SDL_HAPTIC_FRICTION */
SDL_HapticDirection direction; /**< Direction of the effect. */
@@ -747,7 +767,7 @@ typedef struct SDL_HapticCondition
typedef struct SDL_HapticRamp
{
/* Header */
Uint16 type; /**< SDL_HAPTIC_RAMP */
SDL_HapticEffectType type; /**< SDL_HAPTIC_RAMP */
SDL_HapticDirection direction; /**< Direction of the effect. */
/* Replay */
@@ -786,7 +806,7 @@ typedef struct SDL_HapticRamp
typedef struct SDL_HapticLeftRight
{
/* Header */
Uint16 type; /**< SDL_HAPTIC_LEFTRIGHT */
SDL_HapticEffectType type; /**< SDL_HAPTIC_LEFTRIGHT */
/* Replay */
Uint32 length; /**< Duration of the effect in milliseconds. */
@@ -816,7 +836,7 @@ typedef struct SDL_HapticLeftRight
typedef struct SDL_HapticCustom
{
/* Header */
Uint16 type; /**< SDL_HAPTIC_CUSTOM */
SDL_HapticEffectType type; /**< SDL_HAPTIC_CUSTOM */
SDL_HapticDirection direction; /**< Direction of the effect. */
/* Replay */
@@ -915,7 +935,7 @@ typedef struct SDL_HapticCustom
typedef union SDL_HapticEffect
{
/* Common for all force feedback effects */
Uint16 type; /**< Effect type. */
SDL_HapticEffectType type; /**< Effect type. */
SDL_HapticConstant constant; /**< Constant effect. */
SDL_HapticPeriodic periodic; /**< Periodic effect. */
SDL_HapticCondition condition; /**< Condition effect. */
@@ -1193,7 +1213,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HapticEffectSupported(SDL_Haptic *haptic, c
* \sa SDL_RunHapticEffect
* \sa SDL_UpdateHapticEffect
*/
extern SDL_DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect);
extern SDL_DECLSPEC SDL_HapticEffectID SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect);
/**
* Update the properties of an effect.
@@ -1215,7 +1235,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const
* \sa SDL_CreateHapticEffect
* \sa SDL_RunHapticEffect
*/
extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, const SDL_HapticEffect *data);
extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect, const SDL_HapticEffect *data);
/**
* Run the haptic effect on its associated haptic device.
@@ -1239,7 +1259,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int
* \sa SDL_StopHapticEffect
* \sa SDL_StopHapticEffects
*/
extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations);
extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect, Uint32 iterations);
/**
* Stop the haptic effect on its associated haptic device.
@@ -1254,7 +1274,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int eff
* \sa SDL_RunHapticEffect
* \sa SDL_StopHapticEffects
*/
extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int effect);
extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect);
/**
* Destroy a haptic effect on the device.
@@ -1269,7 +1289,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int ef
*
* \sa SDL_CreateHapticEffect
*/
extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect);
extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect);
/**
* Get the status of the current effect on the specified haptic device.
@@ -1285,7 +1305,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int
*
* \sa SDL_GetHapticFeatures
*/
extern SDL_DECLSPEC bool SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect);
extern SDL_DECLSPEC bool SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, SDL_HapticEffectID effect);
/**
* Set the global gain of the specified haptic device.

View File

@@ -1072,8 +1072,8 @@ extern "C" {
*
* By default, SDL will try all available GPU backends in a reasonable order
* until it finds one that can work, but this hint allows the app or user to
* force a specific target, such as "direct3d11" if, say, your hardware
* supports D3D12 but want to try using D3D11 instead.
* force a specific target, such as "direct3d12" if, say, your hardware
* supports Vulkan but you want to try using D3D12 instead.
*
* This hint should be set before any GPU functions are called.
*
@@ -1746,6 +1746,18 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_8BITDO "SDL_JOYSTICK_HIDAPI_8BITDO"
/**
* A variable controlling whether the HIDAPI driver for Flydigi controllers
* should be used.
*
* This variable can be set to the following values:
*
* "0" - HIDAPI driver is not used. "1" - HIDAPI driver is used.
*
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
*/
#define SDL_HINT_JOYSTICK_HIDAPI_FLYDIGI "SDL_JOYSTICK_HIDAPI_FLYDIGI"
/**
* A variable controlling whether the HIDAPI driver for Nintendo Switch
* controllers should be used.
@@ -1949,6 +1961,41 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED"
/**
* A variable controlling whether the new HIDAPI driver for wired Xbox One
* (GIP) controllers should be used.
*
* The variable can be set to the following values:
*
* - "0": HIDAPI driver is not used.
* - "1": HIDAPI driver is used.
*
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE.
*
* This hint should be set before initializing joysticks and gamepads.
*
* \since This hint is available since SDL 3.4.0.
*/
#define SDL_HINT_JOYSTICK_HIDAPI_GIP "SDL_JOYSTICK_HIDAPI_GIP"
/**
* A variable controlling whether the new HIDAPI driver for wired Xbox One
* (GIP) controllers should reset the controller if it can't get the metadata
* from the controller.
*
* The variable can be set to the following values:
*
* - "0": Assume this is a generic controller.
* - "1": Reset the controller to get metadata.
*
* By default the controller is not reset.
*
* This hint should be set before initializing joysticks and gamepads.
*
* \since This hint is available since SDL 3.4.0.
*/
#define SDL_HINT_JOYSTICK_HIDAPI_GIP_RESET_FOR_METADATA "SDL_JOYSTICK_HIDAPI_GIP_RESET_FOR_METADATA"
/**
* A variable controlling whether IOKit should be used for controller
* handling.
@@ -2049,8 +2096,8 @@ extern "C" {
*
* The variable can be set to the following values:
*
* - "0": RAWINPUT drivers are not used.
* - "1": RAWINPUT drivers are used. (default)
* - "0": RAWINPUT drivers are not used. (default)
* - "1": RAWINPUT drivers are used.
*
* This hint should be set before SDL is initialized.
*

View File

@@ -79,7 +79,7 @@ typedef Uint32 SDL_InitFlags;
#define SDL_INIT_AUDIO 0x00000010u /**< `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` */
#define SDL_INIT_VIDEO 0x00000020u /**< `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS`, should be initialized on the main thread */
#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD */
#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS` */
#define SDL_INIT_HAPTIC 0x00001000u
#define SDL_INIT_GAMEPAD 0x00002000u /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */
#define SDL_INIT_EVENTS 0x00004000u
@@ -101,7 +101,7 @@ typedef Uint32 SDL_InitFlags;
* to run.
*
* See
* [Main callbacks in SDL3](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3)
* [Main callbacks in SDL3](https://wiki.libsdl.org/SDL3/README-main-functions#main-callbacks-in-sdl3)
* for complete details.
*
* \since This enum is available since SDL 3.2.0.

View File

@@ -823,7 +823,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS8(SDL_IOStream *src, Sint8 *value);
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -846,7 +846,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -869,7 +869,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -892,7 +892,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -915,7 +915,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -938,7 +938,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -961,7 +961,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -984,7 +984,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -1007,7 +1007,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -1030,7 +1030,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -1053,7 +1053,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.
@@ -1076,7 +1076,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value)
*
* \param src the stream from which to read data.
* \param value a pointer filled in with the data read.
* \returns true on successful write or false on failure; call SDL_GetError()
* \returns true on successful read or false on failure; call SDL_GetError()
* for more information.
*
* \threadsafety This function is not thread safe.

View File

@@ -206,6 +206,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetLogPriorities(void);
* SDL_LOG_PRIORITY_WARN and higher have a prefix showing their priority, e.g.
* "WARNING: ".
*
* This function makes a copy of its string argument, **prefix**, so it is not
* necessary to keep the value of **prefix** alive after the call returns.
*
* \param priority the SDL_LogPriority to modify.
* \param prefix the prefix to use for that log priority, or NULL to use no
* prefix.

View File

@@ -47,7 +47,7 @@
*
* For more information, see:
*
* https://wiki.libsdl.org/SDL3/README/main-functions
* https://wiki.libsdl.org/SDL3/README-main-functions
*/
#ifndef SDL_main_h_
@@ -68,7 +68,7 @@
* proper entry point for the platform, and all the other magic details
* needed, like manually calling SDL_SetMainReady.
*
* Please see [README/main-functions](README/main-functions), (or
* Please see [README-main-functions](README-main-functions), (or
* docs/README-main-functions.md in the source tree) for a more detailed
* explanation.
*
@@ -85,7 +85,7 @@
* SDL_AppQuit. The app should not provide a `main` function in this case, and
* doing so will likely cause the build to fail.
*
* Please see [README/main-functions](README/main-functions), (or
* Please see [README-main-functions](README-main-functions), (or
* docs/README-main-functions.md in the source tree) for a more detailed
* explanation.
*
@@ -512,7 +512,7 @@ typedef int (SDLCALL *SDL_main_func)(int argc, char *argv[]);
* SDL_MAIN_USE_CALLBACKS.
*
* Program startup is a surprisingly complex topic. Please see
* [README/main-functions](README/main-functions), (or
* [README-main-functions](README-main-functions), (or
* docs/README-main-functions.md in the source tree) for a more detailed
* explanation.
*
@@ -618,8 +618,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_EnterAppMainCallbacks(int argc, char *argv[]
* \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 true on success or false on failure; call SDL_GetError() for more

View File

@@ -147,6 +147,19 @@ typedef enum SDL_MouseWheelDirection
*/
typedef Uint32 SDL_MouseButtonFlags;
#define SDL_BUTTON_LEFT 1
#define SDL_BUTTON_MIDDLE 2
#define SDL_BUTTON_RIGHT 3
#define SDL_BUTTON_X1 4
#define SDL_BUTTON_X2 5
#define SDL_BUTTON_MASK(X) (1u << ((X)-1))
#define SDL_BUTTON_LMASK SDL_BUTTON_MASK(SDL_BUTTON_LEFT)
#define SDL_BUTTON_MMASK SDL_BUTTON_MASK(SDL_BUTTON_MIDDLE)
#define SDL_BUTTON_RMASK SDL_BUTTON_MASK(SDL_BUTTON_RIGHT)
#define SDL_BUTTON_X1MASK SDL_BUTTON_MASK(SDL_BUTTON_X1)
#define SDL_BUTTON_X2MASK SDL_BUTTON_MASK(SDL_BUTTON_X2)
/**
* A callback used to transform mouse motion delta from raw values.
*
@@ -174,7 +187,7 @@ typedef Uint32 SDL_MouseButtonFlags;
* with proper synchronization practices when adding other side
* effects beyond mutation of the x and y values.
*
* \since This datatype is available since SDL 3.2.6.
* \since This datatype is available since SDL 3.4.0.
*
* \sa SDL_SetRelativeMouseTransform
*/
@@ -186,20 +199,6 @@ typedef void (SDLCALL *SDL_MouseMotionTransformCallback)(
float *x, float *y
);
#define SDL_BUTTON_LEFT 1
#define SDL_BUTTON_MIDDLE 2
#define SDL_BUTTON_RIGHT 3
#define SDL_BUTTON_X1 4
#define SDL_BUTTON_X2 5
#define SDL_BUTTON_MASK(X) (1u << ((X)-1))
#define SDL_BUTTON_LMASK SDL_BUTTON_MASK(SDL_BUTTON_LEFT)
#define SDL_BUTTON_MMASK SDL_BUTTON_MASK(SDL_BUTTON_MIDDLE)
#define SDL_BUTTON_RMASK SDL_BUTTON_MASK(SDL_BUTTON_RIGHT)
#define SDL_BUTTON_X1MASK SDL_BUTTON_MASK(SDL_BUTTON_X1)
#define SDL_BUTTON_X2MASK SDL_BUTTON_MASK(SDL_BUTTON_X2)
/* Function prototypes */
/**
@@ -579,15 +578,16 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data,
/**
* Create a color cursor.
*
* If this function is passed a surface with alternate representations, the
* surface will be interpreted as the content to be used for 100% display
* scale, and the alternate representations will be used for high DPI
* situations. For example, if the original surface is 32x32, then on a 2x
* macOS display or 200% display scale on Windows, a 64x64 version of the
* image will be used, if available. If a matching version of the image isn't
* available, the closest larger size image will be downscaled to the
* appropriate size and be used instead, if available. Otherwise, the closest
* smaller image will be upscaled and be used instead.
* If this function is passed a surface with alternate representations added
* with SDL_AddSurfaceAlternateImage(), the surface will be interpreted as the
* content to be used for 100% display scale, and the alternate
* representations will be used for high DPI situations. For example, if the
* original surface is 32x32, then on a 2x macOS display or 200% display scale
* on Windows, a 64x64 version of the image will be used, if available. If a
* matching version of the image isn't available, the closest larger size
* image will be downscaled to the appropriate size and be used instead, if
* available. Otherwise, the closest smaller image will be upscaled and be
* used instead.
*
* \param surface an SDL_Surface structure representing the cursor image.
* \param hot_x the x position of the cursor hot spot.
@@ -599,6 +599,7 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data,
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_AddSurfaceAlternateImage
* \sa SDL_CreateCursor
* \sa SDL_CreateSystemCursor
* \sa SDL_DestroyCursor

View File

@@ -517,7 +517,7 @@ typedef enum SDL_PackedLayout
* ABGR32, define a platform-independent encoding into bytes in the order
* specified. For example, in RGB24 data, each pixel is encoded in 3 bytes
* (red, green, blue) in that order, and in ABGR32 data, each pixel is
* encoded in 4 bytes alpha, blue, green, red) in that order. Use these
* encoded in 4 bytes (alpha, blue, green, red) in that order. Use these
* names if the property of a format that is important to you is the order
* of the bytes in memory or on disk.
* - Names with a bit count per component, such as ARGB8888 and XRGB1555, are

View File

@@ -317,7 +317,7 @@
#define SDL_PLATFORM_CYGWIN 1
#endif
#if defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN)
#if (defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN)) && !defined(__NGAGE__)
/**
* A preprocessor macro that is only defined if compiling for Windows.
@@ -473,4 +473,15 @@
#define SDL_PLATFORM_3DS 1
#endif
#ifdef __NGAGE__
/**
* A preprocessor macro that is only defined if compiling for the Nokia
* N-Gage.
*
* \since This macro is available since SDL 3.4.0.
*/
#define SDL_PLATFORM_NGAGE 1
#endif
#endif /* SDL_platform_defines_h_ */

View File

@@ -195,6 +195,12 @@ typedef enum SDL_ProcessIO
* run in the background. In this case the default input and output is
* `SDL_PROCESS_STDIO_NULL` and the exitcode of the process is not
* available, and will always be 0.
* - `SDL_PROP_PROCESS_CREATE_CMDLINE_STRING`: a string containing the program
* to run and any parameters. This string is passed directly to
* `CreateProcess` on Windows, and does nothing on other platforms. This
* property is only important if you want to start programs that does
* non-standard command-line processing, and in most cases using
* `SDL_PROP_PROCESS_CREATE_ARGS_POINTER` is sufficient.
*
* On POSIX platforms, wait() and waitpid(-1, ...) should not be called, and
* SIGCHLD should not be ignored or handled because those would prevent SDL
@@ -231,6 +237,7 @@ extern SDL_DECLSPEC SDL_Process * SDLCALL SDL_CreateProcessWithProperties(SDL_Pr
#define SDL_PROP_PROCESS_CREATE_STDERR_POINTER "SDL.process.create.stderr_source"
#define SDL_PROP_PROCESS_CREATE_STDERR_TO_STDOUT_BOOLEAN "SDL.process.create.stderr_to_stdout"
#define SDL_PROP_PROCESS_CREATE_BACKGROUND_BOOLEAN "SDL.process.create.background"
#define SDL_PROP_PROCESS_CREATE_CMDLINE_STRING "SDL.process.create.cmdline"
/**
* Get the properties associated with a process.

View File

@@ -110,7 +110,7 @@ typedef enum SDL_TextureAddressMode
SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO, /**< Wrapping is enabled if texture coordinates are outside [0, 1], this is the default */
SDL_TEXTURE_ADDRESS_CLAMP, /**< Texture coordinates are clamped to the [0, 1] range */
SDL_TEXTURE_ADDRESS_WRAP, /**< The texture is repeated (tiled) */
SDL_TEXTURE_ADDRESS_WRAP /**< The texture is repeated (tiled) */
} SDL_TextureAddressMode;
/**
@@ -1666,8 +1666,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, S
* Return whether an explicit rectangle was set as the viewport.
*
* This is useful if you're saving and restoring the viewport and want to know
* whether you should restore a specific rectangle or NULL. Note that the
* viewport is always reset when changing rendering targets.
* whether you should restore a specific rectangle or NULL.
*
* Each render target has its own viewport. This function checks the viewport
* for the current render target.

View File

@@ -4656,7 +4656,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_atanf(float x);
*
* Domain: `-INF <= x <= INF`, `-INF <= y <= INF`
*
* Range: `-Pi/2 <= y <= Pi/2`
* Range: `-Pi <= y <= Pi`
*
* This function operates on double-precision floating point values, use
* SDL_atan2f for single-precision floats.
@@ -4692,7 +4692,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_atan2(double y, double x);
*
* Domain: `-INF <= x <= INF`, `-INF <= y <= INF`
*
* Range: `-Pi/2 <= y <= Pi/2`
* Range: `-Pi <= y <= Pi`
*
* This function operates on single-precision floating point values, use
* SDL_atan2 for double-precision floats.
@@ -5974,8 +5974,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

@@ -334,6 +334,10 @@ typedef struct SDL_Storage SDL_Storage;
/**
* Opens up a read-only container for the application's filesystem.
*
* By default, SDL_OpenTitleStorage uses the generic storage implementation.
* When the path override is not provided, the generic implementation will use
* the output of SDL_GetBasePath as the base path.
*
* \param override a path to override the backend's default title root.
* \param props a property list that may contain backend-specific information.
* \returns a title storage container on success or NULL on failure; call

View File

@@ -32,7 +32,8 @@
* There is also a simple .bmp loader, SDL_LoadBMP(). SDL itself does not
* provide loaders for various other file formats, but there are several
* excellent external libraries that do, including its own satellite library,
* SDL_image:
* [SDL_image](https://wiki.libsdl.org/SDL3_image)
* :
*
* https://github.com/libsdl-org/SDL_image
*/
@@ -1136,9 +1137,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD
* If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or
* `dst`) is copied while ensuring clipping to `dst->clip_rect`.
*
* The final blit rectangles are saved in `srcrect` and `dstrect` after all
* clipping is performed.
*
* The blit function should not be called on a locked surface.
*
* The blit semantics for surfaces with and without blending and colorkey are
@@ -1283,10 +1281,11 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src
*
* \param src the SDL_Surface structure to be copied from.
* \param srcrect the SDL_Rect structure representing the rectangle to be
* copied, may not be NULL.
* copied, or NULL to copy the entire surface.
* \param dst the SDL_Surface structure that is the blit target.
* \param dstrect the SDL_Rect structure representing the target rectangle in
* the destination surface, may not be NULL.
* the destination surface, or NULL to fill the entire
* destination surface.
* \param scaleMode the SDL_ScaleMode to be used.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.

View File

@@ -247,14 +247,14 @@ typedef void (SDLCALL *SDL_iOSAnimationCallback)(void *userdata);
*
* For more information see:
*
* https://wiki.libsdl.org/SDL3/README/ios
* https://wiki.libsdl.org/SDL3/README-ios
*
* Note that if you use the "main callbacks" instead of a standard C `main`
* function, you don't have to use this API, as SDL will manage this for you.
*
* Details on main callbacks are here:
*
* https://wiki.libsdl.org/SDL3/README/main-functions
* https://wiki.libsdl.org/SDL3/README-main-functions
*
* \param window the window for which the animation callback should be set.
* \param interval the number of frames after which **callback** will be

View File

@@ -148,13 +148,14 @@ extern "C" {
extern SDL_DECLSPEC int SDLCALL SDL_GetVersion(void);
/**
* Get the code revision of SDL that is linked against your program.
* Get the code revision of the SDL library that is linked against your
* program.
*
* This value is the revision of the code you are linked with and may be
* This value is the revision of the code you are linking against and may be
* different from the code you are compiling with, which is found in the
* constant SDL_REVISION.
*
* The revision is arbitrary string (a hash value) uniquely identifying the
* The revision is an arbitrary string (a hash value) uniquely identifying the
* exact revision of the SDL library in use, and is only useful in comparing
* against other revisions. It is NOT an incrementing number.
*

View File

@@ -1188,6 +1188,16 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int
* Popup windows implicitly do not have a border/decorations and do not appear
* on the taskbar/dock or in lists of windows such as alt-tab menus.
*
* By default, popup window positions will automatically be constrained to
* keep the entire window within display bounds. This can be overridden with
* the `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN` property.
*
* By default, popup menus will automatically grab keyboard focus from the
* parent when shown. This behavior can be overridden by setting the
* `SDL_WINDOW_NOT_FOCUSABLE` flag, setting the
* `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN` property to false, or toggling
* it after creation via the `SDL_SetWindowFocusable()` function.
*
* If a parent window is hidden or destroyed, any child popup windows will be
* recursively hidden or destroyed as well. Child popup windows not explicitly
* hidden will be restored when the parent is shown.
@@ -1228,6 +1238,10 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
* be always on top
* - `SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has no
* window decoration
* - `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN`: true if the "tooltip"
* and "menu" window types should be automatically constrained to be
* entirely within display bounds (default), false if no constraints on the
* position are desired.
* - `SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN`: true if the
* window will be used with an externally managed graphics context.
* - `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should
@@ -1289,7 +1303,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
* - `SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` - true if
* the application wants to use the Wayland surface for a custom role and
* does not want it attached to an XDG toplevel window. See
* [README/wayland](README/wayland) for more information on using custom
* [README-wayland](README-wayland) for more information on using custom
* surfaces.
* - `SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN` - true if the
* application wants an associated `wl_egl_window` object to be created and
@@ -1297,7 +1311,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
* property or `SDL_WINDOW_OPENGL` flag set.
* - `SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER` - the wl_surface
* associated with the window, if you want to wrap an existing window. See
* [README/wayland](README/wayland) for more information.
* [README-wayland](README-wayland) for more information.
*
* These are additional supported properties on Windows:
*
@@ -1356,6 +1370,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop
#define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "SDL.window.create.always_on_top"
#define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "SDL.window.create.borderless"
#define SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN "SDL.window.create.constrain_popup"
#define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "SDL.window.create.focusable"
#define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "SDL.window.create.external_graphics_context"
#define SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER "SDL.window.create.flags"
@@ -1501,8 +1516,8 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window)
*
* On OpenVR:
*
* - `SDL_PROP_WINDOW_OPENVR_OVERLAY_ID`: the OpenVR Overlay Handle ID for the
* associated overlay window.
* - `SDL_PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER`: the OpenVR Overlay Handle ID
* for the associated overlay window.
*
* On Vivante:
*
@@ -1587,7 +1602,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window
#define SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev"
#define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window"
#define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag"
#define SDL_PROP_WINDOW_OPENVR_OVERLAY_ID "SDL.window.openvr.overlay_id"
#define SDL_PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER "SDL.window.openvr.overlay_id"
#define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display"
#define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window"
#define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface"
@@ -1665,15 +1680,16 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window);
/**
* Set the icon for a window.
*
* If this function is passed a surface with alternate representations, the
* surface will be interpreted as the content to be used for 100% display
* scale, and the alternate representations will be used for high DPI
* situations. For example, if the original surface is 32x32, then on a 2x
* macOS display or 200% display scale on Windows, a 64x64 version of the
* image will be used, if available. If a matching version of the image isn't
* available, the closest larger size image will be downscaled to the
* appropriate size and be used instead, if available. Otherwise, the closest
* smaller image will be upscaled and be used instead.
* If this function is passed a surface with alternate representations added
* using SDL_AddSurfaceAlternateImage(), the surface will be interpreted as
* the content to be used for 100% display scale, and the alternate
* representations will be used for high DPI situations. For example, if the
* original surface is 32x32, then on a 2x macOS display or 200% display scale
* on Windows, a 64x64 version of the image will be used, if available. If a
* matching version of the image isn't available, the closest larger size
* image will be downscaled to the appropriate size and be used instead, if
* available. Otherwise, the closest smaller image will be upscaled and be
* used instead.
*
* \param window the window to change.
* \param icon an SDL_Surface structure containing the icon for the window.
@@ -1683,6 +1699,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window);
* \threadsafety This function should only be called on the main thread.
*
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_AddSurfaceAlternateImage
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon);
@@ -1876,7 +1894,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSafeArea(SDL_Window *window, SDL_R
extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowAspectRatio(SDL_Window *window, float min_aspect, float max_aspect);
/**
* Get the size of a window's client area.
* Get the aspect ratio of a window's client area.
*
* \param window the window to query the width and height from.
* \param min_aspect a pointer filled in with the minimum aspect ratio of the

View File

@@ -51,14 +51,14 @@
extern "C" {
#endif
/* Avoid including vulkan.h, don't define VkInstance if it's already included */
#ifdef VULKAN_H_
/* Avoid including vulkan_core.h, don't define VkInstance if it's already included */
#ifdef VULKAN_CORE_H_
#define NO_SDL_VULKAN_TYPEDEFS
#endif
#ifndef NO_SDL_VULKAN_TYPEDEFS
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64)
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
#else
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;

View File

@@ -33,6 +33,10 @@
#cmakedefine SDL_PLATFORM_PRIVATE 1
#ifdef SDL_PLATFORM_PRIVATE
#include "SDL_begin_config_private.h"
#endif
#cmakedefine HAVE_GCC_ATOMICS 1
#cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1
@@ -277,6 +281,7 @@
#cmakedefine SDL_AUDIO_DRIVER_PSP 1
#cmakedefine SDL_AUDIO_DRIVER_PS2 1
#cmakedefine SDL_AUDIO_DRIVER_N3DS 1
#cmakedefine SDL_AUDIO_DRIVER_NGAGE 1
#cmakedefine SDL_AUDIO_DRIVER_QNX 1
#cmakedefine SDL_AUDIO_DRIVER_PRIVATE 1
@@ -365,6 +370,9 @@
#cmakedefine SDL_TIME_PSP 1
#cmakedefine SDL_TIME_PS2 1
#cmakedefine SDL_TIME_N3DS 1
#cmakedefine SDL_TIME_NGAGE 1
#cmakedefine SDL_TIME_PRIVATE 1
/* Enable various timer systems */
#cmakedefine SDL_TIMER_HAIKU 1
@@ -387,6 +395,7 @@
#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@
#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM@
#cmakedefine SDL_VIDEO_DRIVER_N3DS 1
#cmakedefine SDL_VIDEO_DRIVER_NGAGE 1
#cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN 1
#cmakedefine SDL_VIDEO_DRIVER_PS2 1
#cmakedefine SDL_VIDEO_DRIVER_PSP 1
@@ -438,6 +447,7 @@
#cmakedefine SDL_VIDEO_RENDER_VULKAN 1
#cmakedefine SDL_VIDEO_RENDER_OGL 1
#cmakedefine SDL_VIDEO_RENDER_OGL_ES2 1
#cmakedefine SDL_VIDEO_RENDER_NGAGE 1
#cmakedefine SDL_VIDEO_RENDER_PS2 1
#cmakedefine SDL_VIDEO_RENDER_PSP 1
#cmakedefine SDL_VIDEO_RENDER_VITA_GXM 1
@@ -467,6 +477,8 @@
#cmakedefine SDL_GPU_VULKAN 1
#cmakedefine SDL_GPU_METAL 1
#cmakedefine SDL_GPU_PRIVATE 1
/* Enable system power support */
#cmakedefine SDL_POWER_ANDROID 1
#cmakedefine SDL_POWER_LINUX 1
@@ -501,6 +513,8 @@
/* Enable system storage support */
#cmakedefine SDL_STORAGE_STEAM @SDL_STORAGE_STEAM@
#cmakedefine SDL_STORAGE_PRIVATE 1
/* Enable system FSops support */
#cmakedefine SDL_FSOPS_POSIX 1
#cmakedefine SDL_FSOPS_WINDOWS 1
@@ -544,6 +558,11 @@
#cmakedefine SDL_VIDEO_VITA_PVR 1
#cmakedefine SDL_VIDEO_VITA_PVR_OGL 1
/* xkbcommon version info */
#define SDL_XKBCOMMON_VERSION_MAJOR @SDL_XKBCOMMON_VERSION_MAJOR@
#define SDL_XKBCOMMON_VERSION_MINOR @SDL_XKBCOMMON_VERSION_MINOR@
#define SDL_XKBCOMMON_VERSION_PATCH @SDL_XKBCOMMON_VERSION_PATCH@
/* Libdecor version info */
#define SDL_LIBDECOR_VERSION_MAJOR @SDL_LIBDECOR_VERSION_MAJOR@
#define SDL_LIBDECOR_VERSION_MINOR @SDL_LIBDECOR_VERSION_MINOR@

View File

@@ -728,6 +728,8 @@ const char *SDL_GetPlatform(void)
return "macOS";
#elif defined(SDL_PLATFORM_NETBSD)
return "NetBSD";
#elif defined(SDL_PLATFORM_NGAGE)
return "Nokia N-Gage";
#elif defined(SDL_PLATFORM_OPENBSD)
return "OpenBSD";
#elif defined(SDL_PLATFORM_OS2)

View File

@@ -20,6 +20,8 @@
*/
#include "SDL_internal.h"
#include "stdlib/SDL_vacopy.h"
// Simple error handling in SDL
#include "SDL_error_c.h"

View File

@@ -87,7 +87,7 @@ static void SDLCALL CleanupHintProperty(void *userdata, void *value)
SDL_free(hint);
}
static const char* GetHintEnvironmentVariable(const char *name)
static const char *GetHintEnvironmentVariable(const char *name)
{
const char *result = SDL_getenv(name);
if (!result && name && *name) {

View File

@@ -265,6 +265,12 @@ extern "C" {
#include "SDL_utils_c.h"
#include "SDL_hashtable.h"
#define PUSH_SDL_ERROR() \
{ char *_error = SDL_strdup(SDL_GetError());
#define POP_SDL_ERROR() \
SDL_SetError("%s", _error); SDL_free(_error); }
// Do any initialization that needs to happen before threads are started
extern void SDL_InitMainThread(void);

View File

@@ -587,6 +587,25 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S
return;
}
#if defined(SDL_PLATFORM_NGAGE)
extern void NGAGE_vnprintf(char *buf, size_t size, const char *fmt, va_list ap);
char buf[1024];
NGAGE_vnprintf(buf, sizeof(buf), fmt, ap);
#ifdef ENABLE_FILE_LOG
FILE* file;
file = fopen("E:/SDL_Log.txt", "a");
if (file)
{
vfprintf(file, fmt, ap);
fprintf(file, "\n");
(void)fclose(file);
}
#endif
return;
#endif
// Render into stack buffer
va_copy(aq, ap);
len = SDL_vsnprintf(stack_buf, sizeof(stack_buf), fmt, aq);
@@ -767,9 +786,14 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
(void)fclose(pFile);
}
}
#elif defined(SDL_PLATFORM_NGAGE)
{
/* Nothing to do here. */
}
#endif
#if defined(HAVE_STDIO_H) && \
!(defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))) && \
!(defined(SDL_PLATFORM_NGAGE)) && \
!(defined(SDL_PLATFORM_WIN32))
(void)fprintf(stderr, "%s%s\n", GetLogPriorityPrefix(priority), message);
#endif

View File

@@ -163,7 +163,7 @@ bool SDL_CompareAndSwapAtomicU32(SDL_AtomicU32 *a, Uint32 oldval, Uint32 newval)
#elif defined(HAVE_GCC_ATOMICS)
return __sync_bool_compare_and_swap(&a->value, oldval, newval);
#elif defined(SDL_PLATFORM_MACOS) // this is deprecated in 10.12 sdk; favor gcc atomics.
return OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*)&a->value);
return OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t *)&a->value);
#elif defined(SDL_PLATFORM_SOLARIS)
SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(uint_t) == sizeof(a->value));
return ((Uint32)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval);

View File

@@ -77,6 +77,9 @@ static const AudioBootStrap *const bootstrap[] = {
#ifdef SDL_AUDIO_DRIVER_N3DS
&N3DSAUDIO_bootstrap,
#endif
#ifdef SDL_AUDIO_DRIVER_NGAGE
&NGAGEAUDIO_bootstrap,
#endif
#ifdef SDL_AUDIO_DRIVER_EMSCRIPTEN
&EMSCRIPTENAUDIO_bootstrap,
#endif
@@ -410,6 +413,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid,
SDL_LockRWLockForReading(current_audio.device_hash_lock);
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev);
if (logdev) {
SDL_assert(logdev->instance_id == devid);
device = logdev->physical_device;
SDL_assert(device != NULL);
RefPhysicalAudioDevice(device); // reference it, in case the logical device migrates to a new default.
@@ -459,6 +463,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // !
} else {
SDL_LockRWLockForReading(current_audio.device_hash_lock);
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
SDL_assert(device->instance_id == devid);
SDL_UnlockRWLock(current_audio.device_hash_lock);
if (!device) {
@@ -883,6 +888,7 @@ static bool SDLCALL FindLowestDeviceID(void *userdata, const SDL_HashTable *tabl
if (isphysical && (devid_recording == data->recording) && (devid < data->highest)) {
data->highest = devid;
data->result = (SDL_AudioDevice *) value;
SDL_assert(data->result->instance_id == devid);
}
return true; // keep iterating.
}
@@ -1051,7 +1057,10 @@ static bool SDLCALL DestroyOnePhysicalAudioDevice(void *userdata, const SDL_Hash
const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key;
const bool isphysical = !!(devid & (1<<1));
if (isphysical) {
DestroyPhysicalAudioDevice((SDL_AudioDevice *) value);
SDL_AudioDevice *dev = (SDL_AudioDevice *) value;
SDL_assert(dev->instance_id == devid);
DestroyPhysicalAudioDevice(dev);
}
return true; // keep iterating.
}
@@ -1064,9 +1073,16 @@ void SDL_QuitAudio(void)
current_audio.impl.DeinitializeStart();
// Destroy any audio streams that still exist...
while (current_audio.existing_streams) {
SDL_DestroyAudioStream(current_audio.existing_streams);
// Destroy any audio streams that still exist...unless app asked to keep it.
SDL_AudioStream *next = NULL;
for (SDL_AudioStream *i = current_audio.existing_streams; i; i = next) {
next = i->next;
if (i->simplified || SDL_GetBooleanProperty(i->props, SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN, true)) {
SDL_DestroyAudioStream(i);
} else {
i->prev = NULL;
i->next = NULL;
}
}
SDL_LockRWLockForWriting(current_audio.device_hash_lock);
@@ -1147,7 +1163,20 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &device->spec, NULL, NULL));
const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
int br = 0;
if (!SDL_GetAtomicInt(&logdev->paused)) {
if (logdev->iteration_start) {
logdev->iteration_start(logdev->iteration_userdata, logdev->instance_id, true);
}
br = SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
if (logdev->iteration_end) {
logdev->iteration_end(logdev->iteration_userdata, logdev->instance_id, false);
}
}
if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow.
failed = true;
SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die.
@@ -1185,6 +1214,10 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
SDL_memset(mix_buffer, '\0', work_buffer_size); // start with silence.
}
if (logdev->iteration_start) {
logdev->iteration_start(logdev->iteration_userdata, logdev->instance_id, true);
}
for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) {
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &outspec, NULL, NULL));
@@ -1207,6 +1240,10 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
}
}
if (logdev->iteration_end) {
logdev->iteration_end(logdev->iteration_userdata, logdev->instance_id, false);
}
if (postmix) {
SDL_assert(mix_buffer == device->postmix_buffer);
postmix(logdev->postmix_userdata, &outspec, mix_buffer, work_buffer_size);
@@ -1385,6 +1422,7 @@ static int SDLCALL RecordingAudioThread(void *devicep) // thread entry point
typedef struct CountAudioDevicesData
{
int devs_seen;
int devs_skipped;
const int num_devices;
SDL_AudioDeviceID *result;
const bool recording;
@@ -1400,8 +1438,14 @@ static bool SDLCALL CountAudioDevices(void *userdata, const SDL_HashTable *table
const bool isphysical = !!(devid & (1<<1));
if (isphysical && (devid_recording == data->recording)) {
SDL_assert(data->devs_seen < data->num_devices);
SDL_AudioDevice *device = (SDL_AudioDevice *) value; // this is normally risky, but we hold the device_hash_lock here.
const bool zombie = SDL_GetAtomicInt(&device->zombie) != 0;
if (zombie) {
data->devs_skipped++;
} else {
data->result[data->devs_seen++] = devid;
}
}
return true; // keep iterating.
}
@@ -1416,10 +1460,11 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, bool recording)
num_devices = SDL_GetAtomicInt(recording ? &current_audio.recording_device_count : &current_audio.playback_device_count);
result = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID));
if (result) {
CountAudioDevicesData data = { 0, num_devices, result, recording };
CountAudioDevicesData data = { 0, 0, num_devices, result, recording };
SDL_IterateHashTable(current_audio.device_hash, CountAudioDevices, &data);
SDL_assert(data.devs_seen == num_devices);
result[data.devs_seen] = 0; // null-terminated.
SDL_assert((data.devs_seen + data.devs_skipped) == num_devices);
num_devices = data.devs_seen; // might be less if we skipped any.
result[num_devices] = 0; // null-terminated.
}
}
SDL_UnlockRWLock(current_audio.device_hash_lock);
@@ -1464,6 +1509,7 @@ static bool SDLCALL FindAudioDeviceByCallback(void *userdata, const SDL_HashTabl
SDL_AudioDevice *device = (SDL_AudioDevice *) value;
if (data->callback(device, data->userdata)) { // found it?
data->retval = device;
SDL_assert(data->retval->instance_id == devid);
return false; // stop iterating, we found it.
}
}
@@ -1502,12 +1548,33 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle)
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
{
// bit #1 of devid is set for physical devices and unset for logical.
const bool islogical = !(devid & (1<<1));
const char *result = NULL;
SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
if (device) {
const void *vdev = NULL;
if (!SDL_GetCurrentAudioDriver()) {
SDL_SetError("Audio subsystem is not initialized");
} else {
// This does not call ObtainPhysicalAudioDevice() because the device's name never changes, so
// it doesn't have to lock the whole device. However, just to make sure the device pointer itself
// remains valid (in case the device is unplugged at the wrong moment), we hold the
// device_hash_lock while we copy the string.
SDL_LockRWLockForReading(current_audio.device_hash_lock);
SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, &vdev);
if (!vdev) {
SDL_SetError("Invalid audio device instance ID");
} else if (islogical) {
const SDL_LogicalAudioDevice *logdev = (const SDL_LogicalAudioDevice *) vdev;
SDL_assert(logdev->instance_id == devid);
result = SDL_GetPersistentString(logdev->physical_device->name);
} else {
const SDL_AudioDevice *device = (const SDL_AudioDevice *) vdev;
SDL_assert(device->instance_id == devid);
result = SDL_GetPersistentString(device->name);
}
ReleaseAudioDevice(device);
SDL_UnlockRWLock(current_audio.device_hash_lock);
}
return result;
}
@@ -1539,8 +1606,10 @@ int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count)
SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
if (device) {
channels = device->spec.channels;
if (channels > 0 && device->chmap) {
result = SDL_ChannelMapDup(device->chmap, channels);
}
}
ReleaseAudioDevice(device);
if (count) {
@@ -1715,13 +1784,18 @@ static bool OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec
SDL_copyp(&spec, inspec ? inspec : &device->default_spec);
PrepareAudioFormat(device->recording, &spec);
/* We allow the device format to change if it's better than the current settings (by various definitions of "better"). This prevents
something low quality, like an old game using S8/8000Hz audio, from ruining a music thing playing at CD quality that tries to open later.
(or some VoIP library that opens for mono output ruining your surround-sound game because it got there first).
/* We impose a simple minimum on device formats. This prevents something low quality, like an old game using S8/8000Hz audio,
from ruining a music thing playing at CD quality that tries to open later, or some VoIP library that opens for mono output
ruining your surround-sound game because it got there first.
These are just requests! The backend may change any of these values during OpenDevice method! */
device->spec.format = (SDL_AUDIO_BITSIZE(device->default_spec.format) >= SDL_AUDIO_BITSIZE(spec.format)) ? device->default_spec.format : spec.format;
device->spec.freq = SDL_max(device->default_spec.freq, spec.freq);
device->spec.channels = SDL_max(device->default_spec.channels, spec.channels);
const SDL_AudioFormat minimum_format = device->recording ? DEFAULT_AUDIO_RECORDING_FORMAT : DEFAULT_AUDIO_PLAYBACK_FORMAT;
const int minimum_channels = device->recording ? DEFAULT_AUDIO_RECORDING_CHANNELS : DEFAULT_AUDIO_PLAYBACK_CHANNELS;
const int minimum_freq = device->recording ? DEFAULT_AUDIO_RECORDING_FREQUENCY : DEFAULT_AUDIO_PLAYBACK_FREQUENCY;
device->spec.format = (SDL_AUDIO_BITSIZE(minimum_format) >= SDL_AUDIO_BITSIZE(spec.format)) ? minimum_format : spec.format;
device->spec.channels = SDL_max(minimum_channels, spec.channels);
device->spec.freq = SDL_max(minimum_freq, spec.freq);
device->sample_frames = SDL_GetDefaultSampleFramesFromFreq(device->spec.freq);
SDL_UpdatedAudioDeviceFormat(device); // start this off sane.
@@ -1889,8 +1963,9 @@ bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallba
{
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
bool result = true;
bool result = false;
if (logdev) {
result = true;
if (callback && !device->postmix_buffer) {
device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size);
if (!device->postmix_buffer) {
@@ -1909,6 +1984,21 @@ bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallba
return result;
}
bool SDL_SetAudioIterationCallbacks(SDL_AudioDeviceID devid, SDL_AudioIterationCallback iter_start, SDL_AudioIterationCallback iter_end, void *userdata)
{
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
bool result = false;
if (logdev) {
logdev->iteration_start = iter_start;
logdev->iteration_end = iter_end;
logdev->iteration_userdata = userdata;
result = true;
}
ReleaseAudioDevice(device);
return result;
}
bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *streams, int num_streams)
{
const bool islogical = !(devid & (1<<1));

View File

@@ -280,7 +280,7 @@ void ConvertAudio(int num_frames,
// swizzle input to "standard" format if necessary.
if (src_map) {
void* buf = scratch ? scratch : dst; // use scratch if available, since it has to be big enough to hold src, unless it's NULL, then dst has to be.
void *buf = scratch ? scratch : dst; // use scratch if available, since it has to be big enough to hold src, unless it's NULL, then dst has to be.
SwizzleAudio(num_frames, buf, src, src_channels, src_map, src_format);
src = buf;
}
@@ -318,7 +318,7 @@ void ConvertAudio(int num_frames,
// get us to float format.
if (srcconvert) {
void* buf = (channelconvert || dstconvert) ? scratch : dst;
void *buf = (channelconvert || dstconvert) ? scratch : dst;
ConvertAudioToFloat((float *) buf, src, num_frames * src_channels, src_format);
src = buf;
}
@@ -332,7 +332,7 @@ void ConvertAudio(int num_frames,
buf[i] *= gain;
}
} else {
float *fsrc = (float *)src;
const float *fsrc = (const float *)src;
for (int i = 0; i < total_samples; i++) {
buf[i] = fsrc[i] * gain;
}
@@ -368,7 +368,7 @@ void ConvertAudio(int num_frames,
channel_converter = override;
}
void* buf = dstconvert ? scratch : dst;
void *buf = dstconvert ? scratch : dst;
channel_converter((float *) buf, (const float *) src, num_frames);
src = buf;
}
@@ -399,7 +399,7 @@ static int CalculateMaxFrameSize(SDL_AudioFormat src_format, int src_channels, S
return max_format_size * max_channels;
}
static Sint64 GetAudioStreamResampleRate(SDL_AudioStream* stream, int src_freq, Sint64 resample_offset)
static Sint64 GetAudioStreamResampleRate(SDL_AudioStream *stream, int src_freq, Sint64 resample_offset)
{
src_freq = (int)((float)src_freq * stream->freq_ratio);
@@ -768,16 +768,48 @@ bool SDL_SetAudioStreamGain(SDL_AudioStream *stream, float gain)
static bool CheckAudioStreamIsFullySetup(SDL_AudioStream *stream)
{
if (stream->src_spec.format == 0) {
if (stream->src_spec.format == SDL_AUDIO_UNKNOWN) {
return SDL_SetError("Stream has no source format");
} else if (stream->dst_spec.format == 0) {
} else if (stream->dst_spec.format == SDL_AUDIO_UNKNOWN) {
return SDL_SetError("Stream has no destination format");
}
return true;
}
static bool PutAudioStreamBuffer(SDL_AudioStream *stream, const void *buf, int len, SDL_ReleaseAudioBufferCallback callback, void* userdata)
// you MUST hold `stream->lock` when calling this, and validate your parameters!
static bool PutAudioStreamBufferInternal(SDL_AudioStream *stream, const SDL_AudioSpec *spec, const int *chmap, const void *buf, int len, SDL_ReleaseAudioBufferCallback callback, void *userdata)
{
SDL_AudioTrack *track = NULL;
if (callback) {
track = SDL_CreateAudioTrack(stream->queue, spec, chmap, (Uint8 *)buf, len, len, callback, userdata);
if (!track) {
return false;
}
}
const int prev_available = stream->put_callback ? SDL_GetAudioStreamAvailable(stream) : 0;
bool retval = true;
if (track) {
SDL_AddTrackToAudioQueue(stream->queue, track);
} else {
retval = SDL_WriteToAudioQueue(stream->queue, spec, chmap, (const Uint8 *)buf, len);
}
if (retval) {
if (stream->put_callback) {
const int newavail = SDL_GetAudioStreamAvailable(stream) - prev_available;
stream->put_callback(stream->put_callback_userdata, stream, newavail, newavail);
}
}
return retval;
}
static bool PutAudioStreamBuffer(SDL_AudioStream *stream, const void *buf, int len, SDL_ReleaseAudioBufferCallback callback, void *userdata)
{
#if DEBUG_AUDIOSTREAM
SDL_Log("AUDIOSTREAM: wants to put %d bytes", len);
@@ -795,42 +827,16 @@ static bool PutAudioStreamBuffer(SDL_AudioStream *stream, const void *buf, int l
return SDL_SetError("Can't add partial sample frames");
}
SDL_AudioTrack* track = NULL;
if (callback) {
track = SDL_CreateAudioTrack(stream->queue, &stream->src_spec, stream->src_chmap, (Uint8 *)buf, len, len, callback, userdata);
if (!track) {
SDL_UnlockMutex(stream->lock);
return false;
}
}
const int prev_available = stream->put_callback ? SDL_GetAudioStreamAvailable(stream) : 0;
bool result = true;
if (track) {
SDL_AddTrackToAudioQueue(stream->queue, track);
} else {
result = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, stream->src_chmap, (const Uint8 *)buf, len);
}
if (result) {
if (stream->put_callback) {
const int newavail = SDL_GetAudioStreamAvailable(stream) - prev_available;
stream->put_callback(stream->put_callback_userdata, stream, newavail, newavail);
}
}
const bool retval = PutAudioStreamBufferInternal(stream, &stream->src_spec, stream->src_chmap, buf, len, callback, userdata);
SDL_UnlockMutex(stream->lock);
return result;
return retval;
}
static void SDLCALL FreeAllocatedAudioBuffer(void *userdata, const void *buf, int len)
{
SDL_free((void*) buf);
SDL_free((void *)buf);
}
bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
@@ -857,9 +863,8 @@ bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
}
SDL_memcpy(data, buf, len);
buf = data;
bool ret = PutAudioStreamBuffer(stream, buf, len, FreeAllocatedAudioBuffer, NULL);
bool ret = PutAudioStreamBuffer(stream, data, len, FreeAllocatedAudioBuffer, NULL);
if (!ret) {
SDL_free(data);
}
@@ -869,6 +874,181 @@ bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
return PutAudioStreamBuffer(stream, buf, len, NULL, NULL);
}
#define GENERIC_INTERLEAVE_FUNCTION(bits) \
static void InterleaveAudioChannelsGeneric##bits(void *output, const void * const *channel_buffers, const int channels, int num_samples) { \
Uint##bits *dst = (Uint##bits *) output; \
const Uint##bits * const *srcs = (const Uint##bits * const *) channel_buffers; \
for (int frame = 0; frame < num_samples; frame++) { \
for (int channel = 0; channel < channels; channel++) { \
*(dst++) = srcs[channel][frame]; \
} \
} \
}
GENERIC_INTERLEAVE_FUNCTION(8)
GENERIC_INTERLEAVE_FUNCTION(16)
GENERIC_INTERLEAVE_FUNCTION(32)
//GENERIC_INTERLEAVE_FUNCTION(64) (we don't have any 64-bit audio data types at the moment.)
#undef GENERIC_INTERLEAVE_FUNCTION
#define GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(bits) \
static void InterleaveAudioChannelsWithNullsGeneric##bits(void *output, const void * const *channel_buffers, const int channels, int num_samples, const int isilence) { \
const Uint##bits silence = (Uint##bits) isilence; \
Uint##bits *dst = (Uint##bits *) output; \
const Uint##bits * const *srcs = (const Uint##bits * const *) channel_buffers; \
for (int frame = 0; frame < num_samples; frame++) { \
for (int channel = 0; channel < channels; channel++) { \
*(dst++) = srcs[channel] ? srcs[channel][frame] : silence; \
} \
} \
}
GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(8)
GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(16)
GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(32)
//GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(64) (we don't have any 64-bit audio data types at the moment.)
#undef GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION
static void InterleaveAudioChannels(void *output, const void * const *channel_buffers, int channels, int num_samples, const SDL_AudioSpec *spec)
{
bool have_null_channel = false;
void *channels_full[16];
// if didn't specify enough channels, pad out a channel array with NULLs.
if ((channels >= 0) && (channels < spec->channels)) {
have_null_channel = true;
SDL_assert(SDL_IsSupportedChannelCount(spec->channels));
SDL_assert(spec->channels <= SDL_arraysize(channels_full));
SDL_memcpy(channels_full, channel_buffers, channels * sizeof (*channel_buffers));
SDL_memset(channels_full + channels, 0, (spec->channels - channels) * sizeof (*channel_buffers));
channel_buffers = (const void * const *) channels_full;
}
channels = spec->channels; // it's either < 0, needs to be clamped to spec->channels, or we just padded it out to spec->channels with channels_full.
if (!have_null_channel) {
for (int i = 0; i < channels; i++) {
if (channel_buffers[i] == NULL) {
have_null_channel = true;
break;
}
}
}
if (have_null_channel) {
const int silence = SDL_GetSilenceValueForFormat(spec->format);
switch (SDL_AUDIO_BITSIZE(spec->format)) {
case 8: InterleaveAudioChannelsWithNullsGeneric8(output, channel_buffers, channels, num_samples, silence); break;
case 16: InterleaveAudioChannelsWithNullsGeneric16(output, channel_buffers, channels, num_samples, silence); break;
case 32: InterleaveAudioChannelsWithNullsGeneric32(output, channel_buffers, channels, num_samples, silence); break;
//case 64: InterleaveAudioChannelsGeneric64(output, channel_buffers, channels, num_samples); break; (we don't have any 64-bit audio data types at the moment.)
default: SDL_assert(!"Missing needed generic audio interleave function!"); SDL_memset(output, 0, SDL_AUDIO_FRAMESIZE(*spec) * num_samples); break;
}
} else {
// !!! FIXME: it would be possible to do this really well in SIMD for stereo data, using unpack (intel) or zip (arm) instructions, etc.
switch (SDL_AUDIO_BITSIZE(spec->format)) {
case 8: InterleaveAudioChannelsGeneric8(output, channel_buffers, channels, num_samples); break;
case 16: InterleaveAudioChannelsGeneric16(output, channel_buffers, channels, num_samples); break;
case 32: InterleaveAudioChannelsGeneric32(output, channel_buffers, channels, num_samples); break;
//case 64: InterleaveAudioChannelsGeneric64(output, channel_buffers, channels, num_samples); break; (we don't have any 64-bit audio data types at the moment.)
default: SDL_assert(!"Missing needed generic audio interleave function!"); SDL_memset(output, 0, SDL_AUDIO_FRAMESIZE(*spec) * num_samples); break;
}
}
}
bool SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_channels, int num_samples)
{
if (!stream) {
return SDL_InvalidParamError("stream");
} else if (!channel_buffers) {
return SDL_InvalidParamError("channel_buffers");
} else if (num_samples < 0) {
return SDL_InvalidParamError("num_samples");
} else if (num_samples == 0) {
return true; // nothing to do.
}
// we do the interleaving up front without the lock held, so the audio device doesn't starve while we work.
// but we _do_ need to know the current input spec.
SDL_AudioSpec spec;
int chmap_copy[SDL_MAX_CHANNELMAP_CHANNELS];
int *chmap = NULL;
SDL_LockMutex(stream->lock);
if (!CheckAudioStreamIsFullySetup(stream)) {
SDL_UnlockMutex(stream->lock);
return false;
}
SDL_copyp(&spec, &stream->src_spec);
if (stream->src_chmap) {
chmap = chmap_copy;
SDL_memcpy(chmap, stream->src_chmap, sizeof (*chmap) * spec.channels);
}
SDL_UnlockMutex(stream->lock);
if (spec.channels == 1) { // nothing to interleave, just use the usual function.
return SDL_PutAudioStreamData(stream, channel_buffers[0], SDL_AUDIO_FRAMESIZE(spec) * num_samples);
}
bool retval = false;
const int len = SDL_AUDIO_FRAMESIZE(spec) * num_samples;
#if DEBUG_AUDIOSTREAM
SDL_Log("AUDIOSTREAM: wants to put %d bytes of planar data", len);
#endif
// Is the data small enough to just interleave it on the stack and put it through the normal interface?
#define INTERLEAVE_STACK_SIZE 1024
Uint8 stackbuf[INTERLEAVE_STACK_SIZE];
void *data = stackbuf;
SDL_ReleaseAudioBufferCallback callback = NULL;
if (len > INTERLEAVE_STACK_SIZE) {
// too big for the stack? Just SDL_malloc a block and interleave into that. To avoid the extra copy, we'll just set it as a
// new track in the queue (the distinction is specifying a callback to PutAudioStreamBufferInternal, to release the buffer).
data = SDL_malloc(len);
if (!data) {
return false;
}
callback = FreeAllocatedAudioBuffer;
}
InterleaveAudioChannels(data, channel_buffers, num_channels, num_samples, &spec);
// it's okay if the stream format changed on another thread while we didn't hold the lock; PutAudioStreamBufferInternal will notice
// and set up a new track with the right format, and the next SDL_PutAudioStreamData will notice that stream->src_spec doesn't
// match the new track and set up a new one again. It's a bad idea to change the format on another thread while putting here,
// but everything _will_ work out with the format that was (presumably) expected.
SDL_LockMutex(stream->lock);
retval = PutAudioStreamBufferInternal(stream, &spec, chmap, data, len, callback, NULL);
SDL_UnlockMutex(stream->lock);
return retval;
}
static void SDLCALL DontFreeThisAudioBuffer(void *userdata, const void *buf, int len)
{
// We don't own the buffer, but know it will outlive the stream
}
bool SDL_PutAudioStreamDataNoCopy(SDL_AudioStream *stream, const void *buf, int len, SDL_AudioStreamDataCompleteCallback callback, void *userdata)
{
if (!stream) {
return SDL_InvalidParamError("stream");
} else if (!buf) {
return SDL_InvalidParamError("buf");
} else if (len < 0) {
return SDL_InvalidParamError("len");
} else if (len == 0) {
if (callback) {
callback(userdata, buf, len);
}
return true; // nothing to do.
}
return PutAudioStreamBuffer(stream, buf, len, callback ? callback : DontFreeThisAudioBuffer, userdata);
}
bool SDL_FlushAudioStream(SDL_AudioStream *stream)
{
if (!stream) {
@@ -901,8 +1081,8 @@ static Uint8 *EnsureAudioStreamWorkBufferSize(SDL_AudioStream *stream, size_t ne
return ptr;
}
static Sint64 NextAudioStreamIter(SDL_AudioStream* stream, void** inout_iter,
Sint64* inout_resample_offset, SDL_AudioSpec* out_spec, int **out_chmap, bool* out_flushed)
static Sint64 NextAudioStreamIter(SDL_AudioStream *stream, void **inout_iter,
Sint64 *inout_resample_offset, SDL_AudioSpec *out_spec, int **out_chmap, bool *out_flushed)
{
SDL_AudioSpec spec;
bool flushed;
@@ -956,9 +1136,9 @@ static Sint64 NextAudioStreamIter(SDL_AudioStream* stream, void** inout_iter,
return output_frames;
}
static Sint64 GetAudioStreamAvailableFrames(SDL_AudioStream* stream, Sint64* out_resample_offset)
static Sint64 GetAudioStreamAvailableFrames(SDL_AudioStream *stream, Sint64 *out_resample_offset)
{
void* iter = SDL_BeginAudioQueueIter(stream->queue);
void *iter = SDL_BeginAudioQueueIter(stream->queue);
Sint64 resample_offset = stream->resample_offset;
Sint64 output_frames = 0;
@@ -980,9 +1160,9 @@ static Sint64 GetAudioStreamAvailableFrames(SDL_AudioStream* stream, Sint64* out
return output_frames;
}
static Sint64 GetAudioStreamHead(SDL_AudioStream* stream, SDL_AudioSpec* out_spec, int **out_chmap, bool* out_flushed)
static Sint64 GetAudioStreamHead(SDL_AudioStream *stream, SDL_AudioSpec *out_spec, int **out_chmap, bool *out_flushed)
{
void* iter = SDL_BeginAudioQueueIter(stream->queue);
void *iter = SDL_BeginAudioQueueIter(stream->queue);
if (!iter) {
SDL_zerop(out_spec);
@@ -998,8 +1178,8 @@ static Sint64 GetAudioStreamHead(SDL_AudioStream* stream, SDL_AudioSpec* out_spe
// Enough input data MUST be available!
static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int output_frames, float gain)
{
const SDL_AudioSpec* src_spec = &stream->input_spec;
const SDL_AudioSpec* dst_spec = &stream->dst_spec;
const SDL_AudioSpec *src_spec = &stream->input_spec;
const SDL_AudioSpec *dst_spec = &stream->dst_spec;
const SDL_AudioFormat src_format = src_spec->format;
const int src_channels = src_spec->channels;
@@ -1019,7 +1199,7 @@ static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int o
// Not resampling? It's an easy conversion (and maybe not even that!)
if (resample_rate == 0) {
Uint8* work_buffer = NULL;
Uint8 *work_buffer = NULL;
// Ensure we have enough scratch space for any conversions
if ((src_format != dst_format) || (src_channels != dst_channels) || (gain != 1.0f)) {
@@ -1089,7 +1269,7 @@ static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int o
work_buffer_capacity += resample_bytes;
}
Uint8* work_buffer = EnsureAudioStreamWorkBufferSize(stream, work_buffer_capacity);
Uint8 *work_buffer = EnsureAudioStreamWorkBufferSize(stream, work_buffer_capacity);
if (!work_buffer) {
return false;
@@ -1101,7 +1281,7 @@ static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int o
const float postresample_gain = (input_frames > output_frames) ? gain : 1.0f;
// (dst channel map is NULL because we'll do the final swizzle on ConvertAudio after resample.)
const Uint8* input_buffer = SDL_ReadFromAudioQueue(stream->queue,
const Uint8 *input_buffer = SDL_ReadFromAudioQueue(stream->queue,
NULL, resample_format, resample_channels, NULL,
padding_frames, input_frames, padding_frames, work_buffer, preresample_gain);
@@ -1112,11 +1292,11 @@ static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int o
input_buffer += padding_frames * resample_frame_size;
// Decide where the resampled output goes
void* resample_buffer = (resample_buffer_offset != -1) ? (work_buffer + resample_buffer_offset) : buf;
void *resample_buffer = (resample_buffer_offset != -1) ? (work_buffer + resample_buffer_offset) : buf;
SDL_ResampleAudio(resample_channels,
(const float *) input_buffer, input_frames,
(float*) resample_buffer, output_frames,
(const float *)input_buffer, input_frames,
(float *)resample_buffer, output_frames,
resample_rate, &stream->resample_offset);
// Convert to the final format, if necessary (src channel map is NULL because SDL_ReadFromAudioQueue already handled this).
@@ -1326,11 +1506,6 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream)
SDL_free(stream);
}
static void SDLCALL DontFreeThisAudioBuffer(void *userdata, const void *buf, int len)
{
// We don't own the buffer, but know it will outlive the stream
}
bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len, const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len)
{
if (dst_data) {
@@ -1357,8 +1532,7 @@ bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_dat
SDL_AudioStream *stream = SDL_CreateAudioStream(src_spec, dst_spec);
if (stream) {
if (PutAudioStreamBuffer(stream, src_data, src_len, DontFreeThisAudioBuffer, NULL) &&
SDL_FlushAudioStream(stream)) {
if (SDL_PutAudioStreamDataNoCopy(stream, src_data, src_len, NULL, NULL) && SDL_FlushAudioStream(stream)) {
dstlen = SDL_GetAudioStreamAvailable(stream);
if (dstlen >= 0) {
dst = (Uint8 *)SDL_malloc(dstlen);

View File

@@ -25,7 +25,7 @@
// Internal functions used by SDL_AudioStream for queueing audio.
typedef void (SDLCALL *SDL_ReleaseAudioBufferCallback)(void *userdata, const void *buffer, int buflen);
typedef SDL_AudioStreamDataCompleteCallback SDL_ReleaseAudioBufferCallback;
typedef struct SDL_AudioQueue SDL_AudioQueue;
typedef struct SDL_AudioTrack SDL_AudioTrack;

View File

@@ -185,7 +185,7 @@ static void SDL_Convert_F32_to_S32_Scalar(Sint32 *dst, const float *src, int num
#undef SIGNMASK
static void SDL_Convert_Swap16_Scalar(Uint16* dst, const Uint16* src, int num_samples)
static void SDL_Convert_Swap16_Scalar(Uint16 *dst, const Uint16 *src, int num_samples)
{
int i;
@@ -194,7 +194,7 @@ static void SDL_Convert_Swap16_Scalar(Uint16* dst, const Uint16* src, int num_sa
}
}
static void SDL_Convert_Swap32_Scalar(Uint32* dst, const Uint32* src, int num_samples)
static void SDL_Convert_Swap32_Scalar(Uint32 *dst, const Uint32 *src, int num_samples)
{
int i;
@@ -375,7 +375,7 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S8_SSE2(Sint8 *dst, const f
const __m128i bytes = _mm_packus_epi16(shorts0, shorts1);
_mm_store_si128((__m128i*)&dst[i], bytes);
_mm_store_si128((__m128i *)&dst[i], bytes);
})
}
@@ -409,7 +409,7 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_U8_SSE2(Uint8 *dst, const f
const __m128i bytes = _mm_packus_epi16(shorts0, shorts1);
_mm_store_si128((__m128i*)&dst[i], bytes);
_mm_store_si128((__m128i *)&dst[i], bytes);
})
}
@@ -441,8 +441,8 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S16_SSE2(Sint16 *dst, const
const __m128i shorts0 = _mm_packs_epi32(ints0, ints1);
const __m128i shorts1 = _mm_packs_epi32(ints2, ints3);
_mm_store_si128((__m128i*)&dst[i], shorts0);
_mm_store_si128((__m128i*)&dst[i + 8], shorts1);
_mm_store_si128((__m128i *)&dst[i], shorts0);
_mm_store_si128((__m128i *)&dst[i + 8], shorts1);
})
}
@@ -477,55 +477,55 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S32_SSE2(Sint32 *dst, const
const __m128i ints2 = _mm_xor_si128(_mm_cvttps_epi32(values3), _mm_castps_si128(_mm_cmpge_ps(values3, limit)));
const __m128i ints3 = _mm_xor_si128(_mm_cvttps_epi32(values4), _mm_castps_si128(_mm_cmpge_ps(values4, limit)));
_mm_store_si128((__m128i*)&dst[i], ints0);
_mm_store_si128((__m128i*)&dst[i + 4], ints1);
_mm_store_si128((__m128i*)&dst[i + 8], ints2);
_mm_store_si128((__m128i*)&dst[i + 12], ints3);
_mm_store_si128((__m128i *)&dst[i], ints0);
_mm_store_si128((__m128i *)&dst[i + 4], ints1);
_mm_store_si128((__m128i *)&dst[i + 8], ints2);
_mm_store_si128((__m128i *)&dst[i + 12], ints3);
})
}
#endif
// FIXME: SDL doesn't have SSSE3 detection, so use the next one up
#ifdef SDL_SSE4_1_INTRINSICS
static void SDL_TARGETING("ssse3") SDL_Convert_Swap16_SSSE3(Uint16* dst, const Uint16* src, int num_samples)
static void SDL_TARGETING("ssse3") SDL_Convert_Swap16_SSSE3(Uint16 *dst, const Uint16 *src, int num_samples)
{
const __m128i shuffle = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
CONVERT_16_FWD({
dst[i] = SDL_Swap16(src[i]);
}, {
__m128i ints0 = _mm_loadu_si128((const __m128i*)&src[i]);
__m128i ints1 = _mm_loadu_si128((const __m128i*)&src[i + 8]);
__m128i ints0 = _mm_loadu_si128((const __m128i *)&src[i]);
__m128i ints1 = _mm_loadu_si128((const __m128i *)&src[i + 8]);
ints0 = _mm_shuffle_epi8(ints0, shuffle);
ints1 = _mm_shuffle_epi8(ints1, shuffle);
_mm_store_si128((__m128i*)&dst[i], ints0);
_mm_store_si128((__m128i*)&dst[i + 8], ints1);
_mm_store_si128((__m128i *)&dst[i], ints0);
_mm_store_si128((__m128i *)&dst[i + 8], ints1);
})
}
static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const Uint32* src, int num_samples)
static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32 *dst, const Uint32 *src, int num_samples)
{
const __m128i shuffle = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
CONVERT_16_FWD({
dst[i] = SDL_Swap32(src[i]);
}, {
__m128i ints0 = _mm_loadu_si128((const __m128i*)&src[i]);
__m128i ints1 = _mm_loadu_si128((const __m128i*)&src[i + 4]);
__m128i ints2 = _mm_loadu_si128((const __m128i*)&src[i + 8]);
__m128i ints3 = _mm_loadu_si128((const __m128i*)&src[i + 12]);
__m128i ints0 = _mm_loadu_si128((const __m128i *)&src[i]);
__m128i ints1 = _mm_loadu_si128((const __m128i *)&src[i + 4]);
__m128i ints2 = _mm_loadu_si128((const __m128i *)&src[i + 8]);
__m128i ints3 = _mm_loadu_si128((const __m128i *)&src[i + 12]);
ints0 = _mm_shuffle_epi8(ints0, shuffle);
ints1 = _mm_shuffle_epi8(ints1, shuffle);
ints2 = _mm_shuffle_epi8(ints2, shuffle);
ints3 = _mm_shuffle_epi8(ints3, shuffle);
_mm_store_si128((__m128i*)&dst[i], ints0);
_mm_store_si128((__m128i*)&dst[i + 4], ints1);
_mm_store_si128((__m128i*)&dst[i + 8], ints2);
_mm_store_si128((__m128i*)&dst[i + 12], ints3);
_mm_store_si128((__m128i *)&dst[i], ints0);
_mm_store_si128((__m128i *)&dst[i + 4], ints1);
_mm_store_si128((__m128i *)&dst[i + 8], ints2);
_mm_store_si128((__m128i *)&dst[i + 12], ints3);
})
}
#endif
@@ -774,41 +774,41 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
fesetenv(&fenv);
}
static void SDL_Convert_Swap16_NEON(Uint16* dst, const Uint16* src, int num_samples)
static void SDL_Convert_Swap16_NEON(Uint16 *dst, const Uint16 *src, int num_samples)
{
CONVERT_16_FWD({
dst[i] = SDL_Swap16(src[i]);
}, {
uint8x16_t ints0 = vld1q_u8((const Uint8*)&src[i]);
uint8x16_t ints1 = vld1q_u8((const Uint8*)&src[i + 8]);
uint8x16_t ints0 = vld1q_u8((const Uint8 *)&src[i]);
uint8x16_t ints1 = vld1q_u8((const Uint8 *)&src[i + 8]);
ints0 = vrev16q_u8(ints0);
ints1 = vrev16q_u8(ints1);
vst1q_u8((Uint8*)&dst[i], ints0);
vst1q_u8((Uint8*)&dst[i + 8], ints1);
vst1q_u8((Uint8 *)&dst[i], ints0);
vst1q_u8((Uint8 *)&dst[i + 8], ints1);
})
}
static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samples)
static void SDL_Convert_Swap32_NEON(Uint32 *dst, const Uint32 *src, int num_samples)
{
CONVERT_16_FWD({
dst[i] = SDL_Swap32(src[i]);
}, {
uint8x16_t ints0 = vld1q_u8((const Uint8*)&src[i]);
uint8x16_t ints1 = vld1q_u8((const Uint8*)&src[i + 4]);
uint8x16_t ints2 = vld1q_u8((const Uint8*)&src[i + 8]);
uint8x16_t ints3 = vld1q_u8((const Uint8*)&src[i + 12]);
uint8x16_t ints0 = vld1q_u8((const Uint8 *)&src[i]);
uint8x16_t ints1 = vld1q_u8((const Uint8 *)&src[i + 4]);
uint8x16_t ints2 = vld1q_u8((const Uint8 *)&src[i + 8]);
uint8x16_t ints3 = vld1q_u8((const Uint8 *)&src[i + 12]);
ints0 = vrev32q_u8(ints0);
ints1 = vrev32q_u8(ints1);
ints2 = vrev32q_u8(ints2);
ints3 = vrev32q_u8(ints3);
vst1q_u8((Uint8*)&dst[i], ints0);
vst1q_u8((Uint8*)&dst[i + 4], ints1);
vst1q_u8((Uint8*)&dst[i + 8], ints2);
vst1q_u8((Uint8*)&dst[i + 12], ints3);
vst1q_u8((Uint8 *)&dst[i], ints0);
vst1q_u8((Uint8 *)&dst[i + 4], ints1);
vst1q_u8((Uint8 *)&dst[i + 8], ints2);
vst1q_u8((Uint8 *)&dst[i + 12], ints3);
})
}
@@ -839,8 +839,8 @@ static void (*SDL_Convert_F32_to_U8)(Uint8 *dst, const float *src, int num_sampl
static void (*SDL_Convert_F32_to_S16)(Sint16 *dst, const float *src, int num_samples) = NULL;
static void (*SDL_Convert_F32_to_S32)(Sint32 *dst, const float *src, int num_samples) = NULL;
static void (*SDL_Convert_Swap16)(Uint16* dst, const Uint16* src, int num_samples) = NULL;
static void (*SDL_Convert_Swap32)(Uint32* dst, const Uint32* src, int num_samples) = NULL;
static void (*SDL_Convert_Swap16)(Uint16 *dst, const Uint16 *src, int num_samples) = NULL;
static void (*SDL_Convert_Swap32)(Uint32 *dst, const Uint32 *src, int num_samples) = NULL;
void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt)
{
@@ -858,7 +858,7 @@ void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_Audio
break;
case SDL_AUDIO_S16 ^ SDL_AUDIO_MASK_BIG_ENDIAN:
SDL_Convert_Swap16((Uint16*) dst, (const Uint16*) src, num_samples);
SDL_Convert_Swap16((Uint16 *)dst, (const Uint16 *)src, num_samples);
SDL_Convert_S16_to_F32(dst, (const Sint16 *) dst, num_samples);
break;
@@ -867,12 +867,12 @@ void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_Audio
break;
case SDL_AUDIO_S32 ^ SDL_AUDIO_MASK_BIG_ENDIAN:
SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples);
SDL_Convert_Swap32((Uint32 *)dst, (const Uint32 *)src, num_samples);
SDL_Convert_S32_to_F32(dst, (const Sint32 *) dst, num_samples);
break;
case SDL_AUDIO_F32 ^ SDL_AUDIO_MASK_BIG_ENDIAN:
SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples);
SDL_Convert_Swap32((Uint32 *)dst, (const Uint32 *)src, num_samples);
break;
default: SDL_assert(!"Unexpected audio format!"); break;
@@ -896,7 +896,7 @@ void ConvertAudioFromFloat(void *dst, const float *src, int num_samples, SDL_Aud
case SDL_AUDIO_S16 ^ SDL_AUDIO_MASK_BIG_ENDIAN:
SDL_Convert_F32_to_S16((Sint16 *) dst, src, num_samples);
SDL_Convert_Swap16((Uint16*) dst, (const Uint16*) dst, num_samples);
SDL_Convert_Swap16((Uint16 *)dst, (const Uint16 *)dst, num_samples);
break;
case SDL_AUDIO_S32:
@@ -905,22 +905,22 @@ void ConvertAudioFromFloat(void *dst, const float *src, int num_samples, SDL_Aud
case SDL_AUDIO_S32 ^ SDL_AUDIO_MASK_BIG_ENDIAN:
SDL_Convert_F32_to_S32((Sint32 *) dst, src, num_samples);
SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) dst, num_samples);
SDL_Convert_Swap32((Uint32 *)dst, (const Uint32 *)dst, num_samples);
break;
case SDL_AUDIO_F32 ^ SDL_AUDIO_MASK_BIG_ENDIAN:
SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples);
SDL_Convert_Swap32((Uint32 *)dst, (const Uint32 *)src, num_samples);
break;
default: SDL_assert(!"Unexpected audio format!"); break;
}
}
void ConvertAudioSwapEndian(void* dst, const void* src, int num_samples, int bitsize)
void ConvertAudioSwapEndian(void *dst, const void *src, int num_samples, int bitsize)
{
switch (bitsize) {
case 16: SDL_Convert_Swap16((Uint16*) dst, (const Uint16*) src, num_samples); break;
case 32: SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples); break;
case 16: SDL_Convert_Swap16((Uint16 *)dst, (const Uint16 *)src, num_samples); break;
case 32: SDL_Convert_Swap32((Uint32 *)dst, (const Uint32 *)src, num_samples); break;
default: SDL_assert(!"Unexpected audio format!"); break;
}
}

View File

@@ -112,7 +112,7 @@ extern void SDL_AudioThreadFinalize(SDL_AudioDevice *device);
extern void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt);
extern void ConvertAudioFromFloat(void *dst, const float *src, int num_samples, SDL_AudioFormat dst_fmt);
extern void ConvertAudioSwapEndian(void* dst, const void* src, int num_samples, int bitsize);
extern void ConvertAudioSwapEndian(void *dst, const void *src, int num_samples, int bitsize);
extern bool SDL_ChannelMapIsDefault(const int *map, int channels);
extern bool SDL_ChannelMapIsBogus(const int *map, int channels);
@@ -121,7 +121,7 @@ extern bool SDL_ChannelMapIsBogus(const int *map, int channels);
extern void ConvertAudio(int num_frames,
const void *src, SDL_AudioFormat src_format, int src_channels, const int *src_map,
void *dst, SDL_AudioFormat dst_format, int dst_channels, const int *dst_map,
void* scratch, float gain);
void *scratch, float gain);
// Compare two SDL_AudioSpecs, return true if they match exactly.
// Using SDL_memcmp directly isn't safe, since potential padding might not be initialized.
@@ -201,7 +201,7 @@ struct SDL_AudioQueue; // forward decl.
struct SDL_AudioStream
{
SDL_Mutex* lock;
SDL_Mutex *lock;
SDL_PropertiesID props;
@@ -217,7 +217,7 @@ struct SDL_AudioStream
float freq_ratio;
float gain;
struct SDL_AudioQueue* queue;
struct SDL_AudioQueue *queue;
SDL_AudioSpec input_spec; // The spec of input data currently being processed
int *input_chmap;
@@ -264,6 +264,13 @@ struct SDL_LogicalAudioDevice
// true if device was opened with SDL_OpenAudioDeviceStream (so it forbids binding changes, etc).
bool simplified;
// If non-NULL, callback into the app that alerts it to start/end of device iteration.
SDL_AudioIterationCallback iteration_start;
SDL_AudioIterationCallback iteration_end;
// App-supplied pointer for iteration callbacks.
void *iteration_userdata;
// If non-NULL, callback into the app that lets them access the final postmix buffer.
SDL_AudioPostmixCallback postmix;
@@ -386,6 +393,7 @@ extern AudioBootStrap PS2AUDIO_bootstrap;
extern AudioBootStrap PSPAUDIO_bootstrap;
extern AudioBootStrap VITAAUD_bootstrap;
extern AudioBootStrap N3DSAUDIO_bootstrap;
extern AudioBootStrap NGAGEAUDIO_bootstrap;
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
extern AudioBootStrap QSAAUDIO_bootstrap;

View File

@@ -309,6 +309,12 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
// If no specific buffer size has been requested, the device will pick the optimal
if(SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES)) {
ctx.AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2 * device->sample_frames); // AAudio requires that the buffer capacity is at least
ctx.AAudioStreamBuilder_setFramesPerDataCallback(builder, device->sample_frames); // twice the size of the data callback buffer size
}
const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
ctx.AAudioStreamBuilder_setDirection(builder, direction);
ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device);
@@ -366,7 +372,7 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
hidden->processed_bytes = 0;
hidden->callback_bytes = 0;
hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers);
hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers - 1);
if (!hidden->semaphore) {
LOGI("SDL Failed SDL_CreateSemaphore %s recording:%d", SDL_GetError(), recording);
return false;

View File

@@ -31,7 +31,7 @@ SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSamplesPerFrame, (AAudioStreamBuild
SDL_PROC(void, AAudioStreamBuilder_setFormat, (AAudioStreamBuilder * builder, aaudio_format_t format))
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSharingMode, (AAudioStreamBuilder * builder, aaudio_sharing_mode_t sharingMode))
SDL_PROC(void, AAudioStreamBuilder_setDirection, (AAudioStreamBuilder * builder, aaudio_direction_t direction))
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
SDL_PROC(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
SDL_PROC(void, AAudioStreamBuilder_setPerformanceMode, (AAudioStreamBuilder * builder, aaudio_performance_mode_t mode))
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) // API 28
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) // API 28

View File

@@ -38,6 +38,7 @@
#include "../SDL_sysaudio.h"
#include "SDL_alsa_audio.h"
#include "../../core/linux/SDL_udev.h"
#if SDL_ALSA_DEBUG
#define LOGDEBUG(...) SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "ALSA: " __VA_ARGS__)
@@ -87,7 +88,7 @@ static int (*ALSA_snd_device_name_free_hint)(void **);
static snd_pcm_sframes_t (*ALSA_snd_pcm_avail)(snd_pcm_t *);
static size_t (*ALSA_snd_ctl_card_info_sizeof)(void);
static size_t (*ALSA_snd_pcm_info_sizeof)(void);
static int (*ALSA_snd_card_next)(int*);
static int (*ALSA_snd_card_next)(int *);
static int (*ALSA_snd_ctl_open)(snd_ctl_t **,const char *,int);
static int (*ALSA_snd_ctl_close)(snd_ctl_t *);
static int (*ALSA_snd_ctl_card_info)(snd_ctl_t *, snd_ctl_card_info_t *);
@@ -348,28 +349,25 @@ static char *get_pcm_str(void *handle)
// This function waits until it is possible to write a full sound buffer
static bool ALSA_WaitDevice(SDL_AudioDevice *device)
{
const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq);
const int delay = SDL_max(fulldelay, 10);
const int sample_frames = device->sample_frames;
const int fulldelay = (int) ((((Uint64) sample_frames) * 1000) / device->spec.freq);
const int delay = SDL_clamp(fulldelay, 1, 5);
while (!SDL_GetAtomicInt(&device->shutdown)) {
const int rc = ALSA_snd_pcm_wait(device->hidden->pcm, delay);
if (rc < 0 && (rc != -EAGAIN)) {
const int rc = ALSA_snd_pcm_avail(device->hidden->pcm);
if (rc < 0) {
const int status = ALSA_snd_pcm_recover(device->hidden->pcm, rc, 0);
if (status < 0) {
// Hmm, not much we can do - abort
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc));
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA wait failed (unrecoverable): %s", ALSA_snd_strerror(rc));
return false;
}
continue;
}
if (rc > 0) {
break; // ready to go!
if (rc >= sample_frames) {
break;
}
// Timed out! Make sure we aren't shutting down and then wait again.
SDL_Delay(delay);
}
return true;
}
@@ -431,8 +429,11 @@ static int ALSA_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
SDL_assert((buflen % frame_size) == 0);
const snd_pcm_sframes_t total_available = ALSA_snd_pcm_avail(device->hidden->pcm);
const int total_frames = SDL_min(buflen / frame_size, total_available);
if (total_available == 0) {
return 0; // go back to WaitDevice and try again.
}
const int total_frames = SDL_min(buflen / frame_size, total_available);
const int rc = ALSA_snd_pcm_readi(device->hidden->pcm, buffer, total_frames);
SDL_assert(rc != -EAGAIN); // assuming this can't happen if we used snd_pcm_wait and queried for available space. snd_pcm_recover won't handle it!
@@ -671,7 +672,7 @@ static void swizzle_map_compute(const struct ALSA_pcm_cfg_ctx *ctx, int *swizzle
static int alsa_chmap_install(struct ALSA_pcm_cfg_ctx *ctx, const unsigned int *chmap)
{
bool isstack;
snd_pcm_chmap_t *chmap_to_install = (snd_pcm_chmap_t*)SDL_small_alloc(unsigned int, 1 + ctx->chans_n, &isstack);
snd_pcm_chmap_t *chmap_to_install = (snd_pcm_chmap_t *)SDL_small_alloc(unsigned int, 1 + ctx->chans_n, &isstack);
if (!chmap_to_install) {
return -1;
}
@@ -1156,7 +1157,7 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
#if SDL_ALSA_DEBUG
snd_pcm_uframes_t bufsize;
ALSA_snd_pcm_hw_params_get_buffer_size(cfg_ctx.hwparams, &bufsize);
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO,
"ALSA: period size = %ld, periods = %u, buffer size = %lu",
cfg_ctx.persize, cfg_ctx.periods, bufsize);
#endif
@@ -1215,7 +1216,7 @@ static int hotplug_device_process(snd_ctl_t *ctl, snd_ctl_card_info_t *ctl_card_
unsigned int subdev_idx = 0;
const bool recording = direction == SND_PCM_STREAM_CAPTURE ? true : false; // used for the unicity of the device
bool isstack;
snd_pcm_info_t *pcm_info = (snd_pcm_info_t*)SDL_small_alloc(Uint8, ALSA_snd_pcm_info_sizeof(), &isstack);
snd_pcm_info_t *pcm_info = (snd_pcm_info_t *)SDL_small_alloc(Uint8, ALSA_snd_pcm_info_sizeof(), &isstack);
SDL_memset(pcm_info, 0, ALSA_snd_pcm_info_sizeof());
while (true) {
@@ -1445,6 +1446,65 @@ static int SDLCALL ALSA_HotplugThread(void *arg)
}
#endif
#ifdef SDL_USE_LIBUDEV
static bool udev_initialized;
static void ALSA_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
{
if (!devpath) {
return;
}
switch (udev_type) {
case SDL_UDEV_DEVICEADDED:
ALSA_HotplugIteration(NULL, NULL);
break;
case SDL_UDEV_DEVICEREMOVED:
ALSA_HotplugIteration(NULL, NULL);
break;
default:
break;
}
}
static bool ALSA_start_udev()
{
udev_initialized = SDL_UDEV_Init();
if (udev_initialized) {
// Set up the udev callback
if (!SDL_UDEV_AddCallback(ALSA_udev_callback)) {
SDL_UDEV_Quit();
udev_initialized = false;
}
}
return udev_initialized;
}
static void ALSA_stop_udev()
{
if (udev_initialized) {
SDL_UDEV_DelCallback(ALSA_udev_callback);
SDL_UDEV_Quit();
udev_initialized = false;
}
}
#else
static bool ALSA_start_udev()
{
return false;
}
static void ALSA_stop_udev()
{
}
#endif // SDL_USE_LIBUDEV
static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{
ALSA_guess_device_prefix();
@@ -1454,17 +1514,19 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevi
bool has_default_playback = false, has_default_recording = false;
ALSA_HotplugIteration(&has_default_playback, &has_default_recording); // run once now before a thread continues to check.
if (has_default_playback) {
*default_playback = SDL_AddAudioDevice(/*recording=*/false, "ALSA default playback device", NULL, (void*)&default_playback_handle);
*default_playback = SDL_AddAudioDevice(/*recording=*/false, "ALSA default playback device", NULL, (void *)&default_playback_handle);
}
if (has_default_recording) {
*default_recording = SDL_AddAudioDevice(/*recording=*/true, "ALSA default recording device", NULL, (void*)&default_recording_handle);
*default_recording = SDL_AddAudioDevice(/*recording=*/true, "ALSA default recording device", NULL, (void *)&default_recording_handle);
}
if (!ALSA_start_udev()) {
#if SDL_ALSA_HOTPLUG_THREAD
SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 0);
ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", NULL);
// if the thread doesn't spin, oh well, you just don't get further hotplug events.
#endif
}
}
static void ALSA_DeinitializeStart(void)
@@ -1479,6 +1541,7 @@ static void ALSA_DeinitializeStart(void)
ALSA_hotplug_thread = NULL;
}
#endif
ALSA_stop_udev();
// Shutting down! Clean up any data we've gathered.
for (dev = hotplug_devices; dev; dev = next) {

View File

@@ -56,7 +56,7 @@ static bool EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buf
}
for (var j = 0; j < $1; ++j) {
channelData[j] = HEAPF32[buf + (j*numChannels + c)];
channelData[j] = HEAPF32[buf + (j * numChannels + c)];
}
}
}, buffer, buffer_size / framelen);
@@ -189,7 +189,7 @@ static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
}
// limit to native freq
device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; });
device->spec.freq = MAIN_THREAD_EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; });
device->sample_frames = SDL_GetDefaultSampleFramesFromFreq(device->spec.freq) * 2; // double the buffer size, some browsers need more, and we'll just have to live with the latency.
SDL_UpdatedAudioDeviceFormat(device);

View File

@@ -0,0 +1,103 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef SDL_AUDIO_DRIVER_NGAGE
#include "../SDL_sysaudio.h"
#include "SDL_ngageaudio.h"
static SDL_AudioDevice *devptr = NULL;
SDL_AudioDevice *NGAGE_GetAudioDeviceAddr()
{
return devptr;
}
static bool NGAGEAUDIO_OpenDevice(SDL_AudioDevice *device)
{
SDL_PrivateAudioData *phdata = SDL_calloc(1, sizeof(SDL_PrivateAudioData));
if (!phdata) {
SDL_OutOfMemory();
return false;
}
device->hidden = phdata;
phdata->buffer = SDL_calloc(1, device->buffer_size);
if (!phdata->buffer) {
SDL_OutOfMemory();
SDL_free(phdata);
return false;
}
devptr = device;
// Since the phone can change the sample rate during a phone call,
// we set the sample rate to 8KHz to be safe. Even though it
// might be possible to adjust the sample rate dynamically, it's
// not supported by the current implementation.
device->spec.format = SDL_AUDIO_S16LE;
device->spec.channels = 1;
device->spec.freq = 8000;
SDL_UpdatedAudioDeviceFormat(device);
return true;
}
static Uint8 *NGAGEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
{
SDL_PrivateAudioData *phdata = (SDL_PrivateAudioData *)device->hidden;
if (!phdata) {
*buffer_size = 0;
return 0;
}
*buffer_size = device->buffer_size;
return phdata->buffer;
}
static void NGAGEAUDIO_CloseDevice(SDL_AudioDevice *device)
{
if (device->hidden) {
SDL_free(device->hidden->buffer);
SDL_free(device->hidden);
}
return;
}
static bool NGAGEAUDIO_Init(SDL_AudioDriverImpl *impl)
{
impl->OpenDevice = NGAGEAUDIO_OpenDevice;
impl->GetDeviceBuf = NGAGEAUDIO_GetDeviceBuf;
impl->CloseDevice = NGAGEAUDIO_CloseDevice;
impl->ProvidesOwnCallbackThread = true;
impl->OnlyHasDefaultPlaybackDevice = true;
return true;
}
AudioBootStrap NGAGEAUDIO_bootstrap = { "N-Gage", "N-Gage audio driver", NGAGEAUDIO_Init, false };
#endif // SDL_AUDIO_DRIVER_NGAGE

View File

@@ -0,0 +1,368 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "SDL_ngageaudio.h"
#include "../SDL_sysaudio.h"
#include "SDL_internal.h"
#ifdef __cplusplus
}
#endif
#ifdef SDL_AUDIO_DRIVER_NGAGE
#include "SDL_ngageaudio.hpp"
CAudio::CAudio() : CActive(EPriorityStandard), iBufDes(NULL, 0) {}
CAudio *CAudio::NewL(TInt aLatency)
{
CAudio *self = new (ELeave) CAudio();
CleanupStack::PushL(self);
self->ConstructL(aLatency);
CleanupStack::Pop(self);
return self;
}
void CAudio::ConstructL(TInt aLatency)
{
CActiveScheduler::Add(this);
User::LeaveIfError(iTimer.CreateLocal());
iTimerCreated = ETrue;
iStream = CMdaAudioOutputStream::NewL(*this);
if (!iStream) {
SDL_Log("Error: Failed to create audio stream");
User::Leave(KErrNoMemory);
}
iLatency = aLatency;
iLatencySamples = aLatency * 8; // 8kHz.
// Determine minimum and maximum number of samples to write with one
// WriteL request.
iMinWrite = iLatencySamples / 8;
iMaxWrite = iLatencySamples / 2;
// Set defaults.
iState = EStateNone;
iTimerCreated = EFalse;
iTimerActive = EFalse;
}
CAudio::~CAudio()
{
if (iStream) {
iStream->Stop();
while (iState != EStateDone) {
User::After(100000); // 100ms.
}
delete iStream;
}
}
void CAudio::Start()
{
if (iStream) {
// Set to 8kHz mono audio.
iStreamSettings.iChannels = TMdaAudioDataSettings::EChannelsMono;
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate8000Hz;
iStream->Open(&iStreamSettings);
iState = EStateOpening;
} else {
SDL_Log("Error: Failed to open audio stream");
}
}
// Feeds more processed data to the audio stream.
void CAudio::Feed()
{
// If a WriteL is already in progress, or we aren't even playing;
// do nothing!
if ((iState != EStateWriting) && (iState != EStatePlaying)) {
return;
}
// Figure out the number of samples that really have been played
// through the output.
TTimeIntervalMicroSeconds pos = iStream->Position();
TInt played = 8 * (pos.Int64() / TInt64(1000)).GetTInt(); // 8kHz.
played += iBaseSamplesPlayed;
// Determine the difference between the number of samples written to
// CMdaAudioOutputStream and the number of samples it has played.
// The difference is the amount of data in the buffers.
if (played < 0) {
played = 0;
}
TInt buffered = iSamplesWritten - played;
if (buffered < 0) {
buffered = 0;
}
if (iState == EStateWriting) {
return;
}
// The trick for low latency: Do not let the buffers fill up beyond the
// latency desired! We write as many samples as the difference between
// the latency target (in samples) and the amount of data buffered.
TInt samplesToWrite = iLatencySamples - buffered;
// Do not write very small blocks. This should improve efficiency, since
// writes to the streaming API are likely to be expensive.
if (samplesToWrite < iMinWrite) {
// Not enough data to write, set up a timer to fire after a while.
// Try againwhen it expired.
if (iTimerActive) {
return;
}
iTimerActive = ETrue;
SetActive();
iTimer.After(iStatus, (1000 * iLatency) / 8);
return;
}
// Do not write more than the set number of samples at once.
int numSamples = samplesToWrite;
if (numSamples > iMaxWrite) {
numSamples = iMaxWrite;
}
SDL_AudioDevice *device = NGAGE_GetAudioDeviceAddr();
if (device) {
SDL_PrivateAudioData *phdata = (SDL_PrivateAudioData *)device->hidden;
iBufDes.Set(phdata->buffer, 2 * numSamples, 2 * numSamples);
iStream->WriteL(iBufDes);
iState = EStateWriting;
// Keep track of the number of samples written (for latency calculations).
iSamplesWritten += numSamples;
} else {
// Output device not ready yet. Let's go for another round.
if (iTimerActive) {
return;
}
iTimerActive = ETrue;
SetActive();
iTimer.After(iStatus, (1000 * iLatency) / 8);
}
}
void CAudio::RunL()
{
iTimerActive = EFalse;
Feed();
}
void CAudio::DoCancel()
{
iTimerActive = EFalse;
iTimer.Cancel();
}
void CAudio::StartThread()
{
TInt heapMinSize = 8192; // 8 KB initial heap size.
TInt heapMaxSize = 1024 * 1024; // 1 MB maximum heap size.
TInt err = iProcess.Create(_L("ProcessThread"), ProcessThreadCB, KDefaultStackSize * 2, heapMinSize, heapMaxSize, this);
if (err == KErrNone) {
iProcess.SetPriority(EPriorityLess);
iProcess.Resume();
} else {
SDL_Log("Error: Failed to create audio processing thread: %d", err);
}
}
void CAudio::StopThread()
{
if (iStreamStarted) {
iProcess.Kill(KErrNone);
iProcess.Close();
iStreamStarted = EFalse;
}
}
TInt CAudio::ProcessThreadCB(TAny *aPtr)
{
CAudio *self = static_cast<CAudio *>(aPtr);
SDL_AudioDevice *device = NGAGE_GetAudioDeviceAddr();
while (self->iStreamStarted) {
if (device) {
SDL_PlaybackAudioThreadIterate(device);
} else {
device = NGAGE_GetAudioDeviceAddr();
}
User::After(100000); // 100ms.
}
return KErrNone;
}
void CAudio::MaoscOpenComplete(TInt aError)
{
if (aError == KErrNone) {
iStream->SetVolume(1);
iStreamStarted = ETrue;
StartThread();
} else {
SDL_Log("Error: Failed to open audio stream: %d", aError);
}
}
void CAudio::MaoscBufferCopied(TInt aError, const TDesC8 & /*aBuffer*/)
{
if (aError == KErrNone) {
iState = EStatePlaying;
Feed();
} else if (aError == KErrAbort) {
// The stream has been stopped.
iState = EStateDone;
} else {
SDL_Log("Error: Failed to copy audio buffer: %d", aError);
}
}
void CAudio::MaoscPlayComplete(TInt aError)
{
// If we finish due to an underflow, we'll need to restart playback.
// Normally KErrUnderlow is raised at stream end, but in our case the API
// should never see the stream end -- we are continuously feeding it more
// data! Many underflow errors mean that the latency target is too low.
if (aError == KErrUnderflow) {
// The number of samples played gets resetted to zero when we restart
// playback after underflow.
iBaseSamplesPlayed = iSamplesWritten;
iStream->Stop();
Cancel();
iStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate8000Hz, TMdaAudioDataSettings::EChannelsMono);
iState = EStatePlaying;
Feed();
return;
} else if (aError != KErrNone) {
// Handle error.
}
// We shouldn't get here.
SDL_Log("%s: %d", __FUNCTION__, aError);
}
static TBool gAudioRunning;
TBool AudioIsReady()
{
return gAudioRunning;
}
TInt AudioThreadCB(TAny *aParams)
{
CTrapCleanup *cleanup = CTrapCleanup::New();
if (!cleanup) {
return KErrNoMemory;
}
CActiveScheduler *scheduler = new CActiveScheduler();
if (!scheduler) {
delete cleanup;
return KErrNoMemory;
}
CActiveScheduler::Install(scheduler);
TRAPD(err,
{
TInt latency = *(TInt *)aParams;
CAudio *audio = CAudio::NewL(latency);
CleanupStack::PushL(audio);
gAudioRunning = ETrue;
audio->Start();
TBool once = EFalse;
while (gAudioRunning) {
// Allow active scheduler to process any events.
TInt error;
CActiveScheduler::RunIfReady(error, CActive::EPriorityIdle);
if (!once) {
SDL_AudioDevice *device = NGAGE_GetAudioDeviceAddr();
if (device) {
// Stream ready; start feeding audio data.
// After feeding it once, the callbacks will take over.
audio->iState = CAudio::EStatePlaying;
audio->Feed();
once = ETrue;
}
}
User::After(100000); // 100ms.
}
CleanupStack::PopAndDestroy(audio);
});
delete scheduler;
delete cleanup;
return err;
}
RThread audioThread;
void InitAudio(TInt *aLatency)
{
_LIT(KAudioThreadName, "AudioThread");
TInt err = audioThread.Create(KAudioThreadName, AudioThreadCB, KDefaultStackSize, 0, aLatency);
if (err != KErrNone) {
User::Leave(err);
}
audioThread.Resume();
}
void DeinitAudio()
{
gAudioRunning = EFalse;
TRequestStatus status;
audioThread.Logon(status);
User::WaitForRequest(status);
audioThread.Close();
}
#endif // SDL_AUDIO_DRIVER_NGAGE

View File

@@ -0,0 +1,44 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifndef SDL_ngageaudio_h
#define SDL_ngageaudio_h
typedef struct SDL_PrivateAudioData
{
Uint8 *buffer;
} SDL_PrivateAudioData;
#ifdef __cplusplus
extern "C" {
#endif
#include "../SDL_sysaudio.h"
SDL_AudioDevice *NGAGE_GetAudioDeviceAddr();
#ifdef __cplusplus
}
#endif
#endif // SDL_ngageaudio_h

View File

@@ -0,0 +1,98 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL_ngageaudio_hpp
#define SDL_ngageaudio_hpp
#include <e32base.h>
#include <e32std.h>
#include <mda/common/audio.h>
#include <mdaaudiooutputstream.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "../SDL_sysaudio.h"
#include "SDL_ngageaudio.h"
#ifdef __cplusplus
}
#endif
TBool AudioIsReady();
void InitAudio(TInt *aLatency);
void DeinitAudio();
class CAudio : public CActive, public MMdaAudioOutputStreamCallback
{
public:
static CAudio *NewL(TInt aLatency);
~CAudio();
void ConstructL(TInt aLatency);
void Start();
void Feed();
void RunL();
void DoCancel();
static TInt ProcessThreadCB(TAny * /*aPtr*/);
// From MMdaAudioOutputStreamCallback
void MaoscOpenComplete(TInt aError);
void MaoscBufferCopied(TInt aError, const TDesC8 &aBuffer);
void MaoscPlayComplete(TInt aError);
enum
{
EStateNone = 0,
EStateOpening,
EStatePlaying,
EStateWriting,
EStateDone
} iState;
private:
CAudio();
void StartThread();
void StopThread();
CMdaAudioOutputStream *iStream;
TMdaAudioDataSettings iStreamSettings;
TBool iStreamStarted;
TPtr8 iBufDes; // Descriptor for the buffer.
TInt iLatency; // Latency target in ms
TInt iLatencySamples; // Latency target in samples.
TInt iMinWrite; // Min number of samples to write per turn.
TInt iMaxWrite; // Max number of samples to write per turn.
TInt iBaseSamplesPlayed; // amples played before last restart.
TInt iSamplesWritten; // Number of samples written so far.
RTimer iTimer;
TBool iTimerCreated;
TBool iTimerActive;
RThread iProcess;
};
#endif // SDL_ngageaudio_hpp

View File

@@ -546,7 +546,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((struct pw_node*)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);
@@ -1114,7 +1114,13 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
if (!stream_name || *stream_name == '\0') {
stream_name = "Audio Stream";
if (app_name) {
stream_name = app_name;
} else if (app_id) {
stream_name = app_id;
} else {
stream_name = "SDL Audio Stream";
}
}
/*

View File

@@ -269,19 +269,9 @@ static const char *getAppName(void)
return SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING);
}
static void ThreadedMainloopSignal(void)
{
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // alert waiting threads to unblock.
// we need to kill any SDL_SetError state; we didn't create this thread
// so its SDL TLS slot will leak otherwise, so we do this every time
// we're (presumably) losing control of the thread.
SDL_CleanupTLS();
}
static void OperationStateChangeCallback(pa_operation *o, void *userdata)
{
ThreadedMainloopSignal(); // just signal any waiting code, it can look up the details.
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
}
/* This function assume you are holding `mainloop`'s lock. The operation is unref'd in here, assuming
@@ -323,7 +313,7 @@ static void DisconnectFromPulseServer(void)
static void PulseContextStateChangeCallback(pa_context *context, void *userdata)
{
ThreadedMainloopSignal(); // just signal any waiting code, it can look up the details.
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
}
static bool ConnectToPulseServer(void)
@@ -410,7 +400,7 @@ static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata)
struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *)userdata;
//SDL_Log("PULSEAUDIO WRITE CALLBACK! nbytes=%u", (unsigned int) nbytes);
h->bytes_requested += nbytes;
ThreadedMainloopSignal();
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
}
// This function waits until it is possible to write a full sound buffer
@@ -481,7 +471,7 @@ static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata)
{
//SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes);
ThreadedMainloopSignal(); // the recording code queries what it needs, we just need to signal to end any wait
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the recording code queries what it needs, we just need to signal to end any wait
}
static bool PULSEAUDIO_WaitRecordingDevice(SDL_AudioDevice *device)
@@ -602,7 +592,7 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device)
static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata)
{
ThreadedMainloopSignal(); // just signal any waiting code, it can look up the details.
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
}
static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
@@ -682,7 +672,8 @@ static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
paspec.rate = device->spec.freq;
// Reduced prebuffering compared to the defaults.
paattr.fragsize = device->buffer_size; // despite the name, this is only used for recording devices, according to PulseAudio docs!
paattr.fragsize = device->buffer_size * 2; // despite the name, this is only used for recording devices, according to PulseAudio docs! (times 2 because we want _more_ than our buffer size sent from the server at a time, which helps some drivers).
paattr.tlength = device->buffer_size;
paattr.prebuf = -1;
paattr.maxlength = -1;
@@ -803,7 +794,7 @@ static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last,
if (i) {
AddPulseAudioDevice(false, i->description, i->name, i->index, &i->sample_spec);
}
ThreadedMainloopSignal();
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
}
// This is called when PulseAudio adds a recording ("source") device.
@@ -813,7 +804,7 @@ static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_la
if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) {
AddPulseAudioDevice(true, i->description, i->name, i->index, &i->sample_spec);
}
ThreadedMainloopSignal();
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
}
static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data)
@@ -838,7 +829,7 @@ static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *dat
}
}
ThreadedMainloopSignal();
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
}
static bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata)
@@ -882,7 +873,7 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByIndex, (void *)(uintptr_t)idx));
}
}
ThreadedMainloopSignal();
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
}
static bool CheckDefaultDevice(const bool changed, char *device_path)

View File

@@ -130,7 +130,8 @@ static bool VITAAUD_OpenDevice(SDL_AudioDevice *device)
static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
{
return (sceAudioOutOutput(device->hidden->port, buffer) == 0);
// sceAudioOutOutput returns amount of samples queued or < 0 on error
return (sceAudioOutOutput(device->hidden->port, buffer) >= 0);
}
// This function waits until it is possible to write a full sound buffer

View File

@@ -750,7 +750,7 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
// Try querying IAudioClient3 if sharemode is AUDCLNT_SHAREMODE_SHARED
if (sharemode == AUDCLNT_SHAREMODE_SHARED) {
IAudioClient3 *client3 = NULL;
ret = IAudioClient_QueryInterface(client, &SDL_IID_IAudioClient3, (void**)&client3);
ret = IAudioClient_QueryInterface(client, &SDL_IID_IAudioClient3, (void **)&client3);
if (SUCCEEDED(ret)) {
UINT32 default_period_in_frames = 0;
UINT32 fundamental_period_in_frames = 0;

View File

@@ -239,7 +239,7 @@ static void COREMEDIA_CloseDevice(SDL_Camera *device)
hidden.session = nil;
[session stopRunning];
[session removeInput:[session.inputs objectAtIndex:0]];
[session removeOutput:(AVCaptureVideoDataOutput*)[session.outputs objectAtIndex:0]];
[session removeOutput:(AVCaptureVideoDataOutput *)[session.outputs objectAtIndex:0]];
session = nil;
}

View File

@@ -61,7 +61,7 @@ static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, S
SDL3.camera.ctx2d.drawImage(SDL3.camera.video, 0, 0, w, h);
const imgrgba = SDL3.camera.ctx2d.getImageData(0, 0, w, h).data;
Module.HEAPU8.set(imgrgba, rgba);
HEAPU8.set(imgrgba, rgba);
return 1;
}, device->actual_spec.width, device->actual_spec.height, rgba);

View File

@@ -675,7 +675,7 @@ static HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride)
LONG lStride = 0;
// Try to get the default stride from the media type.
HRESULT ret = IMFMediaType_GetUINT32(pType, &SDL_MF_MT_DEFAULT_STRIDE, (UINT32*)&lStride);
HRESULT ret = IMFMediaType_GetUINT32(pType, &SDL_MF_MT_DEFAULT_STRIDE, (UINT32 *)&lStride);
if (FAILED(ret)) {
// Attribute not set. Try to calculate the default stride.
@@ -741,7 +741,7 @@ static bool MEDIAFOUNDATION_OpenDevice(SDL_Camera *device, const SDL_CameraSpec
SDL_Log("CAMERA: opening device with symlink of '%s'", utf8symlink);
#endif
wstrsymlink = WIN_UTF8ToString(utf8symlink);
wstrsymlink = WIN_UTF8ToStringW(utf8symlink);
if (!wstrsymlink) {
goto failed;
}
@@ -901,7 +901,7 @@ static char *QueryActivationObjectString(IMFActivate *activation, const GUID *pg
return NULL;
}
char *utf8str = WIN_StringToUTF8(wstr);
char *utf8str = WIN_StringToUTF8W(wstr);
CoTaskMemFree(wstr);
return utf8str;
}
@@ -1001,7 +1001,7 @@ static void MaybeAddDevice(IMFActivate *activation)
if (name && symlink) {
IMFMediaSource *source = NULL;
// "activating" here only creates an object, it doesn't open the actual camera hardware or start recording.
HRESULT ret = IMFActivate_ActivateObject(activation, &SDL_IID_IMFMediaSource, (void**)&source);
HRESULT ret = IMFActivate_ActivateObject(activation, &SDL_IID_IMFMediaSource, (void **)&source);
if (SUCCEEDED(ret) && source) {
CameraFormatAddData add_data;
GatherCameraSpecs(source, &add_data);

View File

@@ -838,7 +838,7 @@ static void node_event_info(void *object, const struct pw_node_info *info)
if (!(info->params[i].flags & SPA_PARAM_INFO_READ))
continue;
res = pw_node_enum_params((struct pw_node*)g->proxy,
res = pw_node_enum_params((struct pw_node *)g->proxy,
++SPA_PARAMS_INFO_SEQ(info->params[i]), id, 0, -1, NULL);
if (SPA_RESULT_IS_ASYNC(res))
SPA_PARAMS_INFO_SEQ(info->params[i]) = res;

View File

@@ -193,7 +193,7 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
*timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec);
#if DEBUG_CAMERA
SDL_Log("CAMERA: debug mmap: image %d/%d data[0]=%p", buf.index, device->hidden->nb_buffers, (void*)frame->pixels);
SDL_Log("CAMERA: debug mmap: image %d/%d data[0]=%p", buf.index, device->hidden->nb_buffers, (void *)frame->pixels);
#endif
break;
@@ -230,7 +230,7 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
return SDL_CAMERA_FRAME_ERROR;
}
frame->pixels = (void*)buf.m.userptr;
frame->pixels = (void *)buf.m.userptr;
if (device->hidden->driver_pitch) {
frame->pitch = device->hidden->driver_pitch;
} else {
@@ -241,7 +241,7 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
*timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec);
#if DEBUG_CAMERA
SDL_Log("CAMERA: debug userptr: image %d/%d data[0]=%p", buf.index, device->hidden->nb_buffers, (void*)frame->pixels);
SDL_Log("CAMERA: debug userptr: image %d/%d data[0]=%p", buf.index, device->hidden->nb_buffers, (void *)frame->pixels);
#endif
break;

View File

@@ -93,7 +93,7 @@ static void MaybeAddDevice(Sint32 devid)
GatherCameraSpecs(devid, &add_data, &fullname, &position);
if (add_data.num_specs > 0) {
SDL_AddCamera(fullname, position, add_data.num_specs, add_data.specs, (void*)devid);
SDL_AddCamera(fullname, position, add_data.num_specs, add_data.specs, (void *)devid);
}
SDL_free(fullname);
@@ -102,7 +102,7 @@ static void MaybeAddDevice(Sint32 devid)
static SceUID imbUid = -1;
static void freeBuffers(SceCameraInfo* info)
static void freeBuffers(SceCameraInfo *info)
{
if (imbUid != -1) {
sceKernelFreeMemBlock(imbUid);
@@ -118,7 +118,7 @@ static bool VITACAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec
return SDL_SetError("Only one camera can be active");
}
SceCameraInfo* info = (SceCameraInfo*)SDL_calloc(1, sizeof(SceCameraInfo));
SceCameraInfo *info = (SceCameraInfo *)SDL_calloc(1, sizeof(SceCameraInfo));
info->size = sizeof(SceCameraInfo);
info->priority = SCE_CAMERA_PRIORITY_SHARE;
@@ -139,12 +139,12 @@ static bool VITACAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec
info->format = SCE_CAMERA_FORMAT_YUV420_PLANE;
info->pitch = 0; // same size surface
info->sizeIBase = spec->width*spec->height;;
info->sizeIBase = spec->width * spec->height;;
info->sizeUBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
info->sizeVBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
// PHYCONT memory size *must* be a multiple of 1MB, we can just always spend 2MB, since we don't use PHYCONT anywhere else
imbUid = sceKernelAllocMemBlock("CameraI", SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW, 2*1024*1024 , NULL);
imbUid = sceKernelAllocMemBlock("CameraI", SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW, 2 * 1024 * 1024 , NULL);
if (imbUid < 0)
{
return SDL_SetError("sceKernelAllocMemBlock error: 0x%08X", imbUid);
@@ -179,7 +179,7 @@ static void VITACAMERA_CloseDevice(SDL_Camera *device)
if (device->hidden) {
sceCameraStop((int)device->handle);
sceCameraClose((int)device->handle);
freeBuffers((SceCameraInfo*)device->hidden);
freeBuffers((SceCameraInfo *)device->hidden);
SDL_free(device->hidden);
}
}
@@ -205,7 +205,7 @@ static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Sur
*timestampNS = read.timestamp;
SceCameraInfo* info = (SceCameraInfo*)(device->hidden);
SceCameraInfo *info = (SceCameraInfo *)(device->hidden);
frame->pitch = info->width;
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), info->sizeIBase + info->sizeUBase + info->sizeVBase);

View File

@@ -119,7 +119,7 @@ void *SDL_GetAndroidActivity(void)
}
SDL_DECLSPEC const char * SDLCALL SDL_GetAndroidCachePath(void);
const char* SDL_GetAndroidCachePath(void)
const char *SDL_GetAndroidCachePath(void)
{
SDL_Unsupported();
return NULL;
@@ -127,7 +127,7 @@ const char* SDL_GetAndroidCachePath(void)
SDL_DECLSPEC const char * SDLCALL SDL_GetAndroidExternalStoragePath(void);
const char* SDL_GetAndroidExternalStoragePath(void)
const char *SDL_GetAndroidExternalStoragePath(void)
{
SDL_Unsupported();
return NULL;
@@ -172,7 +172,7 @@ bool SDL_SendAndroidMessage(Uint32 command, int param)
}
SDL_DECLSPEC bool SDLCALL SDL_ShowAndroidToast(const char *message, int duration, int gravity, int xoffset, int yoffset);
bool SDL_ShowAndroidToast(const char* message, int duration, int gravity, int xoffset, int yoffset)
bool SDL_ShowAndroidToast(const char *message, int duration, int gravity, int xoffset, int yoffset)
{
(void)message;
(void)duration;

View File

@@ -371,6 +371,7 @@ static jmethodID midShowTextInput;
static jmethodID midSupportsRelativeMouse;
static jmethodID midOpenFileDescriptor;
static jmethodID midShowFileDialog;
static jmethodID midGetPreferredLocales;
// audio manager
static jclass mAudioManagerClass;
@@ -660,6 +661,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
midSupportsRelativeMouse = (*env)->GetStaticMethodID(env, mActivityClass, "supportsRelativeMouse", "()Z");
midOpenFileDescriptor = (*env)->GetStaticMethodID(env, mActivityClass, "openFileDescriptor", "(Ljava/lang/String;Ljava/lang/String;)I");
midShowFileDialog = (*env)->GetStaticMethodID(env, mActivityClass, "showFileDialog", "([Ljava/lang/String;ZZI)Z");
midGetPreferredLocales = (*env)->GetStaticMethodID(env, mActivityClass, "getPreferredLocales", "()Ljava/lang/String;");
if (!midClipboardGetText ||
!midClipboardHasText ||
@@ -691,7 +693,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
!midShowTextInput ||
!midSupportsRelativeMouse ||
!midOpenFileDescriptor ||
!midShowFileDialog) {
!midShowFileDialog ||
!midGetPreferredLocales) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
}
@@ -2585,65 +2588,22 @@ bool Android_JNI_ShowToast(const char *message, int duration, int gravity, int x
bool Android_JNI_GetLocale(char *buf, size_t buflen)
{
AConfiguration *cfg;
SDL_assert(buflen > 6);
// Need to re-create the asset manager if locale has changed (SDL_EVENT_LOCALE_CHANGED)
Internal_Android_Destroy_AssetManager();
if (!asset_manager) {
Internal_Android_Create_AssetManager();
bool result = false;
if (buf && buflen > 0) {
*buf = '\0';
JNIEnv *env = Android_JNI_GetEnv();
jstring string = (jstring)(*env)->CallStaticObjectMethod(env, mActivityClass, midGetPreferredLocales);
if (string) {
const char *utf8string = (*env)->GetStringUTFChars(env, string, NULL);
if (utf8string) {
result = true;
SDL_strlcpy(buf, utf8string, buflen);
(*env)->ReleaseStringUTFChars(env, string, utf8string);
}
if (!asset_manager) {
return false;
}
cfg = AConfiguration_new();
if (!cfg) {
return false;
}
{
char language[2] = {};
char country[2] = {};
size_t id = 0;
AConfiguration_fromAssetManager(cfg, asset_manager);
AConfiguration_getLanguage(cfg, language);
AConfiguration_getCountry(cfg, country);
// Indonesian is "id" according to ISO 639.2, but on Android is "in" because of Java backwards compatibility
if (language[0] == 'i' && language[1] == 'n') {
language[1] = 'd';
}
// copy language (not null terminated)
if (language[0]) {
buf[id++] = language[0];
if (language[1]) {
buf[id++] = language[1];
(*env)->DeleteLocalRef(env, string);
}
}
buf[id++] = '_';
// copy country (not null terminated)
if (country[0]) {
buf[id++] = country[0];
if (country[1]) {
buf[id++] = country[1];
}
}
buf[id++] = '\0';
SDL_assert(id <= buflen);
}
AConfiguration_delete(cfg);
return true;
return result;
}
bool Android_JNI_OpenURL(const char *url)
@@ -2731,7 +2691,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)(
// Convert fileList to string
size_t count = (*env)->GetArrayLength(env, fileList);
char **charFileList = SDL_calloc(count + 1, sizeof(char*));
char **charFileList = SDL_calloc(count + 1, sizeof(char *));
if (charFileList == NULL) {
mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1);
@@ -2787,7 +2747,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)(
}
bool Android_JNI_OpenFileDialog(
SDL_DialogFileCallback callback, void* userdata,
SDL_DialogFileCallback callback, void *userdata,
const SDL_DialogFileFilter *filters, int nfilters, bool forwrite,
bool multiple)
{

View File

@@ -151,7 +151,7 @@ bool SDL_IsAndroidTablet(void);
bool SDL_IsAndroidTV(void);
// File Dialogs
bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void* userdata,
bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void *userdata,
const SDL_DialogFileFilter *filters, int nfilters, bool forwrite,
bool multiple);

View File

@@ -324,7 +324,7 @@ void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted)
{
}
void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data)
void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void *), void *release_callback_data, void (*acquire_callback)(void *), void *acquire_callback_data)
{
}

View File

@@ -105,7 +105,7 @@ bool GDK_RegisterChangeNotifications(void)
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler");
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this) {
if (constrained) {
if (constrained && !((_this->windows) && _this->windows->text_input_active)) {
SDL_SetKeyboardFocus(NULL);
} else {
SDL_SetKeyboardFocus(_this->windows);

View File

@@ -82,7 +82,7 @@ extern "C" SDL_BLooper *SDL_Looper;
class SDL_BLooper : public BLooper
{
public:
SDL_BLooper(const char* name) : BLooper(name)
SDL_BLooper(const char *name) : BLooper(name)
{
#ifdef SDL_VIDEO_OPENGL
_current_context = NULL;

View File

@@ -56,7 +56,7 @@ const char *SDL_signature = "application/x-SDL-executable";
// Create a descendant of BApplication
class SDL_BApp : public BApplication {
public:
SDL_BApp(const char* signature) :
SDL_BApp(const char *signature) :
BApplication(signature) {
}
@@ -65,7 +65,7 @@ public:
}
virtual void RefsReceived(BMessage* message) {
virtual void RefsReceived(BMessage *message) {
entry_ref entryRef;
for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) {
BPath referencePath = BPath(&entryRef);

View File

@@ -49,6 +49,7 @@ static bool LoadDBUSSyms(void)
SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, DBusError *), bus_register);
SDL_DBUS_SYM(void (*)(DBusConnection *, const char *, DBusError *), bus_add_match);
SDL_DBUS_SYM(void (*)(DBusConnection *, const char *, DBusError *), bus_remove_match);
SDL_DBUS_SYM(const char *(*)(DBusConnection *), bus_get_unique_name);
SDL_DBUS_SYM(DBusConnection *(*)(const char *, DBusError *), connection_open_private);
SDL_DBUS_SYM(void (*)(DBusConnection *, dbus_bool_t), connection_set_exit_on_disconnect);
SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *), connection_get_is_connected);
@@ -67,6 +68,7 @@ static bool LoadDBUSSyms(void)
SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, const char *, const char *), message_is_signal);
SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, const char *), message_has_path);
SDL_DBUS_SYM(DBusMessage *(*)(const char *, const char *, const char *, const char *), message_new_method_call);
SDL_DBUS_SYM(DBusMessage *(*)(const char *, const char *, const char *), message_new_signal);
SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, int, ...), message_append_args);
SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, int, va_list), message_append_args_valist);
SDL_DBUS_SYM(void (*)(DBusMessage *, DBusMessageIter *), message_iter_init_append);

View File

@@ -47,6 +47,7 @@ typedef struct SDL_DBusContext
dbus_bool_t (*bus_register)(DBusConnection *, DBusError *);
void (*bus_add_match)(DBusConnection *, const char *, DBusError *);
void (*bus_remove_match)(DBusConnection *, const char *, DBusError *);
const char *(*bus_get_unique_name)(DBusConnection *);
DBusConnection *(*connection_open_private)(const char *, DBusError *);
void (*connection_set_exit_on_disconnect)(DBusConnection *, dbus_bool_t);
dbus_bool_t (*connection_get_is_connected)(DBusConnection *);
@@ -66,6 +67,7 @@ typedef struct SDL_DBusContext
dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *);
dbus_bool_t (*message_has_path)(DBusMessage *, const char *);
DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *);
DBusMessage *(*message_new_signal)(const char *, const char *, const char *);
dbus_bool_t (*message_append_args)(DBusMessage *, int, ...);
dbus_bool_t (*message_append_args_valist)(DBusMessage *, int, va_list);
void (*message_iter_init_append)(DBusMessage *, DBusMessageIter *);

Some files were not shown because too many files have changed in this diff Show More