Compare commits

...
Author SHA1 Message Date
Sam Lantinga 96292a5b46 Updated to version 3.2.20 for release 2025-08-04 09:58:55 -07:00
Petar Popovic ffa618c00b SDL_LoadWAV_IO(): On error, set *audio_buf to NULL and *audio_len to 0
(cherry picked from commit 23e08f7807)
2025-08-03 13:44:37 -04:00
Petar Popovic 291b9b3c82 SDL_enabled_assert(): Use NULL istead of 0 to explicity initialize the pointer members of SDL_AssertData
(cherry picked from commit faf3bd9991)
2025-08-03 13:36:14 -04:00
Frank Praznik ec45117f0f x11: Filter mouse wheel events from "Master" devices
Discard wheel events from "Master" devices to avoid duplicates, as wheel events are stateless and can't be deduplicated.

(cherry picked from commit 51ce3f8c8d)
2025-08-02 18:57:44 -04:00
Frank Praznik 0d7aff9c56 GPU: Vulkan backend flags command buffer for cleanup when swapchain is requested
When skipping presentation due to the window being hidden, presentDataCount is not incremented on the command buffer, and subsequently the submitted command buffers will not be cleaned up as long as the window is hidden. This results in a lag spike when showing the window due to all previously submitted command buffers suddenly being cleaned up at once, and lag at shutdown due to an equivalent number of fences needing to be destroyed.

Instead of relying on presentDataCount to determine whether a command buffer should be cleaned up, use a flag, which is set under the appropriate circumstances.

(cherry picked from commit 42463569d5)
2025-08-02 09:24:21 -07:00
Petar Popovic d31b239288 Fix double-free warning in src/hidapi/linux/hid.c
(cherry picked from commit ae5ce258cf)
2025-08-02 07:09:12 -07:00
capehill b1cadf0e99 Fix SDL_BlitSurfaceScaled crash
SDL_BlitSurfaceScaled could crash when passed large coordinates, due
to final_dst.w or final_dst.h getting negative values.

(cherry picked from commit 1c5c3b1479)
2025-08-01 09:22:38 -07:00
Frank Praznik c1f67585e6 wayland: Cleanup an outdated conditional and comment
There may have been a reason for not attaching a null buffer when destroying a popup at some point in the past, but that is unnecessary now, as is the comment about ShowWindow crashing, as ShowWindow assures that a null buffer is attached before (re)creating the window.

(cherry picked from commit 550d95e04f)
2025-08-01 10:40:32 -04:00
A1029384756 93988e28c0 wayland: reorder surface destruction to avoid premature blanking
(cherry picked from commit 9034375d2f)
2025-08-01 10:40:32 -04:00
Matthew Zavislak edef6e66e9 Support Google Play 16 KB Page Size Requirement (#13470)
- See: https://developer.android.com/guide/practices/page-sizes#update-packaging
- Also, make min API uniform at 21 (from 16 and 23 in a few places)

(cherry picked from commit dc2c83c383)
2025-07-31 16:21:02 -07:00
Petar Popovic e3f47809c4 Fix potential memory leak in SDL_render_gles2.c
(cherry picked from commit 09221820f6)
2025-07-31 16:19:10 -07:00
cosmonaut f759e7ac59 GPU: Bail out of aquiring Vulkan swapchain if window is hidden
(cherry picked from commit c5edf4bd5b)
2025-07-31 16:03:19 -07:00
Frank Praznik 544eb2c5a9 wayland: Adjust popup adjoining check
The previous calculation could result in a window whose original position was positioned exactly corner-to-corner with the parent not being adjusted to be adjoining, and thus subject to spurious closure.

(cherry picked from commit b0cdb7143f)
2025-07-31 12:13:54 -04:00
Cheney Wang 30e3eba20a GPU: Fix wrong Vulkan swapchain size when retrying acquire
(cherry picked from commit d8ac51859e)
2025-07-30 15:35:23 -07:00
Wouter Wijsman f0e85a2a9c psp: fix audio not playing
(cherry picked from commit 3d1a28ccf2)
2025-07-30 13:11:23 -07:00
Thaddeus Crews 106af5b46a Define relevant macros when LACKS_ERRNO_H is true
(cherry picked from commit 3195980b49)
2025-07-30 09:11:22 -07:00
Stefan Schlosser 522716ed90 SDL_getenv.c: fix dynamic loading of environ symbol on FreeBSD
The current implementation uses the returned address of the `dlsym` function
directly to load the `environ` symbol. But this function doesn't return the
address to the symbol itself, instead it returns the address to the location
where the actual address is stored, i.e. it's an additional indirection.
Consequently, the implementation fails to load and process the environment
variables successfully.

One example where this error shows up is in the `Dialog API`: in an `X11`
environment, the `zenity` driver requires access to the user's `DISPLAY` and
`XAUTHORITY` environment variables. Because these variables aren't transfered
to the `zenity` process, no dialogs are shown. This can be exercised in the
`test/testdialog.c` testprogram.

The fix changes the indirection level of the `dlsym` call from `char **` to
`char ***`, does a `NULL`-check in case the call failed, and returns the
dereferenced actual adress to the `environ` symbol.

(cherry picked from commit 10458f2cac)
2025-07-30 07:06:54 -07:00
Evan Hemsley a65fbb0211 GPU: Fix incorrect block size when D3D12 uniform buffer is rotated (#13469)
(cherry picked from commit 07af4b237b)
2025-07-29 15:51:58 -07:00
Petar Popovic 46ec859bd1 Fix two use-after-free warnings
(cherry picked from commit f27dbb22f0)
2025-07-29 12:29:34 -07:00
Xen 2a7aa4eae4 Update SDL_clipboard.h
Typo fixes and a small addition to SDL_SetClipboardData about mime_type list usage clarity.

(cherry picked from commit b3ba1c159e)
2025-07-28 11:59:34 -07:00
Dan Andrus c31ddf021e Check NSWindow::isVisible before sending SDL_WINDOWEVENT_RESTORED during Cocoa_WindowListener::windowDidResize
(cherry picked from commit 30f0aeb26a)
2025-07-28 14:47:45 -04:00
Shootfast eaa2a8239f Fixed typo in SDL_scancode.h
The backslash/vertical line key is between the left shift and "Z" key on ISO keyboards

(cherry picked from commit 507ee033cc)
2025-07-27 19:58:45 -07:00
Brenton Bostick d313ecb737 Fix warning on Android arm-v7
Building SDL for armeabi-v7a gives this warning:
```
SDL/src/audio/SDL_audiotypecvt.c:541:14: warning: '#pragma FENV_ACCESS' is not supported on this target - ignored [-Wignored-pragmas]
  541 | #pragma STDC FENV_ACCESS ON
```

(cherry picked from commit ed4de7aeed)
2025-07-27 08:16:21 -07:00
Petar Popovic 64b2af0340 SDL_gpu.c: Fixed deref-before-check warning
(cherry picked from commit 6a5af95364)
2025-07-26 12:08:57 -07:00
Anonymous Maarten 58d0702948 ci+n3ds: avoid apt-get package manager
- use Unix Makefiles (with parallelization) CMake generator
- use binutils strings binary from devkitpro

(cherry picked from commit e6d200e51c)
2025-07-26 16:06:36 +02:00
Sam Lantinga 707717e94b Reverted: Added Steam Virtual Gamepad support to the GameInput driver
This version of SDL doesn't support newer GameInput versions required for this feature.
2025-07-24 14:00:20 -07:00
Sam Lantinga a140bba55a Fixed building with GameInput v1.0
(cherry picked from commit e5d57d8ad6)
2025-07-24 10:52:28 -07:00
Sam Lantinga f4ddacacd0 Fixed building with GameInput v1.0
(cherry picked from commit 0ee0fe1572)
2025-07-24 10:43:05 -07:00
Sam Lantinga ebba656bdb Added Steam Virtual Gamepad support to the GameInput driver
(cherry picked from commit 66dad9c21f)
2025-07-24 10:38:02 -07:00
Sam Lantinga b78c61d67a Fixed double SDL_EVENT_GAMEPAD_ADDED for controllers with automatic gamepad mappings
(cherry picked from commit 6babade758)
2025-07-24 10:38:02 -07:00
L zard 4210aa61e1 build_config_windows: define HAVE_STDARG/STDDEF_H outside of
condition.
They are defined in both `#if HAVE_LIBC` and its `#else` anyway.
[sdl-ci-filter msvc-*]

(cherry picked from commit ea995b1694)
2025-07-21 14:45:19 -07:00
L zard d8a345d924 build_config_windows: fix HAVE_VSSCANF defined regardless of MSVC version.
[sdl-ci-filter msvc-*]

(cherry picked from commit a977a11fa6)
2025-07-21 14:45:19 -07:00
Acclution b8dc9767da GPU: Fix Vulkan compute uniform descriptor not being marked as set (#13389)
(cherry picked from commit 8bd29f7ca3)
2025-07-18 15:30:05 -07:00
BurntRanch 1ab01b9367 Clarify SDL_GPUVertexBufferDescription.pitch comment (#13381)
(cherry picked from commit ee6d8f78f4)
2025-07-17 08:55:04 -07:00
Sam Lantinga ee371ff740 Fixed crash if a clipboard event was sent with video uninitialized
This can happen if you're using SDL on Android without using the video subsystem.

(cherry picked from commit 855d28e97a)
2025-07-17 08:48:00 -07:00
Evan Hemsley ef58dd77ca GPU: Clean up properties in SDL_ReleaseGPUTexture (#13378) 2025-07-17 00:23:52 -07:00
Ryan C. Gordon e6a7121904 audio: Binding an SDL_AudioStream will set missing formats.
It _must_ have the format set for the opposite side from the device (so
playback needs the src format set, and recording needs the dst format set),
since the stream gets mangled by the device thread if not. So if it has never
been set (stream created with NULL audiospec), just set it to match the device.
If the stream is just meant to buffer and not convert, this is desired
behavior, even if it didn't also fix a bug.

Binding the audio stream will always set the device side's format, as usual;
this does not need to be set by the caller at all.

Fixes #13363.

(cherry picked from commit f2ae6503c0)
2025-07-15 06:44:12 -04:00
Sam Lantinga a6ed8ab59d Updated to version 3.2.19 for development 2025-07-14 11:44:22 -07:00
Sam Lantinga bd40d0ded1 Removed the Mayflash GameCube adapter from the PS3 controller list
(cherry picked from commit 277f91c317)
2025-07-14 11:30:46 -07:00
45 changed files with 279 additions and 120 deletions

No files matched your search

+9 -2
View File
@@ -174,6 +174,7 @@ class JobDetails:
brew_packages: list[str] = dataclasses.field(default_factory=list)
cmake_toolchain_file: str = ""
cmake_arguments: list[str] = dataclasses.field(default_factory=list)
cmake_generator: str = "Ninja"
cmake_build_arguments: list[str] = dataclasses.field(default_factory=list)
clang_tidy: bool = True
cppflags: list[str] = dataclasses.field(default_factory=list)
@@ -222,6 +223,7 @@ class JobDetails:
check_sources: bool = False
setup_python: bool = False
pypi_packages: list[str] = dataclasses.field(default_factory=list)
binutils_strings: str = "strings"
def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
data = {
@@ -255,6 +257,7 @@ class JobDetails:
"cflags": my_shlex_join(self.cppflags + self.cflags),
"cxxflags": my_shlex_join(self.cppflags + self.cxxflags),
"ldflags": my_shlex_join(self.ldflags),
"cmake-generator": self.cmake_generator,
"cmake-toolchain-file": self.cmake_toolchain_file,
"clang-tidy": self.clang_tidy,
"cmake-arguments": my_shlex_join(self.cmake_arguments),
@@ -289,6 +292,7 @@ class JobDetails:
"check-sources": self.check_sources,
"setup-python": self.setup_python,
"pypi-packages": my_shlex_join(self.pypi_packages),
"binutils-strings": self.binutils_strings,
}
return {k: v for k, v in data.items() if v != ""}
@@ -675,13 +679,16 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
case SdlPlatform.N3ds:
job.ccache = True
job.cmake_generator = "Unix Makefiles"
job.cmake_build_arguments.append("-j$(nproc)")
job.ccache = False
job.shared = False
job.apt_packages = ["ccache", "ninja-build", "binutils"]
job.apt_packages = []
job.clang_tidy = False
job.run_tests = False
job.cc_from_cmake = True
job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
job.binutils_strings = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-strings"
job.static_lib = StaticLibType.A
case SdlPlatform.Msys2:
job.ccache = True
+3 -3
View File
@@ -201,7 +201,7 @@ jobs:
#shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -GNinja \
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -G "${{ matrix.platform.cmake-generator }}" \
-Wdeprecated -Wdev -Werror \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-DSDL_WERROR=${{ matrix.platform.werror }} \
@@ -232,9 +232,9 @@ jobs:
run: |
echo "This should show us the SDL_REVISION"
echo "Shared library:"
${{ (matrix.platform.shared-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
${{ (matrix.platform.shared-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
echo "Static library:"
${{ (matrix.platform.static-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
${{ (matrix.platform.static-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
- name: 'Run build-time tests (CMake)'
id: tests
if: ${{ !matrix.platform.no-cmake && matrix.platform.run-tests }}
+4
View File
@@ -107,6 +107,10 @@ LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
LOCAL_LDFLAGS := -Wl,--no-undefined -Wl,--no-undefined-version -Wl,--version-script=$(LOCAL_PATH)/src/dynapi/SDL_dynapi.sym
# https://developer.android.com/guide/practices/page-sizes
LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"
LOCAL_LDFLAGS += "-Wl,-z,common-page-size=16384"
ifeq ($(NDK_DEBUG),1)
cmd-strip :=
endif
+6 -1
View File
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
endif()
# See docs/release_checklist.md
project(SDL3 LANGUAGES C VERSION "3.2.18")
project(SDL3 LANGUAGES C VERSION "3.2.20")
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(SDL3_MAINPROJECT ON)
@@ -1487,6 +1487,11 @@ if(ANDROID)
endif()
endif()
if(TARGET SDL3-shared)
target_link_options(SDL3-shared PRIVATE "-Wl,-z,max-page-size=16384")
target_link_options(SDL3-shared PRIVATE "-Wl,-z,common-page-size=16384")
endif()
elseif(EMSCRIPTEN)
# Hide noisy warnings that intend to aid mostly during initial stages of porting a new
# project. Uncomment at will for verbose cross-compiling -I/../ path info.
+2 -2
View File
@@ -19,10 +19,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.2.18</string>
<string>3.2.20</string>
<key>CFBundleSignature</key>
<string>SDLX</string>
<key>CFBundleVersion</key>
<string>3.2.18</string>
<string>3.2.20</string>
</dict>
</plist>
+4 -4
View File
@@ -3086,7 +3086,7 @@
CLANG_ENABLE_OBJC_ARC = YES;
DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
DYLIB_CURRENT_VERSION = 201.18.0;
DYLIB_CURRENT_VERSION = 201.20.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
@@ -3121,7 +3121,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.2.18;
MARKETING_VERSION = 3.2.20;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
PRODUCT_NAME = SDL3;
@@ -3150,7 +3150,7 @@
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
DYLIB_CURRENT_VERSION = 201.18.0;
DYLIB_CURRENT_VERSION = 201.20.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -3182,7 +3182,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.2.18;
MARKETING_VERSION = 3.2.20;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
+1 -1
View File
@@ -1,4 +1,4 @@
Title SDL 3.2.18
Title SDL 3.2.20
Version 1
Description SDL Library for macOS (http://www.libsdl.org)
DefaultLocation /Library/Frameworks
+1 -1
View File
@@ -19,7 +19,7 @@ android {
abiFilters 'arm64-v8a'
}
cmake {
arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static"
arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static", "-DAPP_SUPPORT_FLEXIBLE_PAGE_SIZES=true"
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
abiFilters 'arm64-v8a'
}
+4 -1
View File
@@ -7,4 +7,7 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
# Min runtime API level
APP_PLATFORM=android-16
APP_PLATFORM=android-21
# https://developer.android.com/guide/practices/page-sizes#update-packaging
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
@@ -26,4 +26,9 @@ endif()
add_library(main SHARED
YourSourceHere.c
)
#https://developer.android.com/guide/practices/page-sizes#update-packaging
target_link_options(main PRIVATE "-Wl,-z,max-page-size=16384")
target_link_options(main PRIVATE "-Wl,-z,common-page-size=16384")
target_link_libraries(main PRIVATE SDL3::SDL3)
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 2;
private static final int SDL_MICRO_VERSION = 18;
private static final int SDL_MICRO_VERSION = 20;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
+7
View File
@@ -30,6 +30,7 @@ abi="arm64-v8a" # "armeabi-v7a arm64-v8a x86 x86_64"
obj=
lib=
ndk_args=
flexpage=true
# Allow an external caller to specify locations and platform.
while [ $# -gt 0 ]; do
@@ -42,6 +43,8 @@ while [ $# -gt 0 ]; do
platform=${arg#APP_PLATFORM=}
elif [ "${arg:0:8}" == "APP_ABI=" ]; then
abi=${arg#APP_ABI=}
elif [ "${arg:0:32}" == "APP_SUPPORT_FLEXIBLE_PAGE_SIZES=" ]; then
flexpage=${arg#APP_SUPPORT_FLEXIBLE_PAGE_SIZES=}
else
ndk_args="$ndk_args $arg"
fi
@@ -67,6 +70,9 @@ done
# APP_* variables set in the environment here will not be seen by the
# ndk-build makefile segments that use them, e.g., default-application.mk.
# For consistency, pass all values on the command line.
#
# Add support for Google Play 16 KB Page size requirement:
# https://developer.android.com/guide/practices/page-sizes#ndk-build
ndk-build \
NDK_PROJECT_PATH=null \
NDK_OUT=$obj \
@@ -75,4 +81,5 @@ ndk-build \
APP_ABI="$abi" \
APP_PLATFORM="$platform" \
APP_MODULES="SDL3" \
APP_SUPPORT_FLEXIBLE_PAGE_SIZES="$flexpage" \
$ndk_args
+1 -1
View File
@@ -20,7 +20,7 @@
*/
/**
* Main include header for the SDL library, version 3.2.18
* Main include header for the SDL library, version 3.2.20
*
* It is almost always best to include just this one header instead of
* picking out individual headers included here. There are exceptions to
+1 -1
View File
@@ -362,7 +362,7 @@ extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *
#define SDL_enabled_assert(condition) \
do { \
while ( !(condition) ) { \
static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \
static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
continue; /* go again. */ \
+4 -1
View File
@@ -942,7 +942,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid);
* Binding a stream to a device will set its output format for playback
* devices, and its input format for recording devices, so they match the
* device's settings. The caller is welcome to change the other end of the
* stream's format at any time with SDL_SetAudioStreamFormat().
* stream's format at any time with SDL_SetAudioStreamFormat(). If the other
* end of the stream's format has never been set (the audio stream was created
* with a NULL audio spec), this function will set it to match the device
* end's format.
*
* \param devid an audio device to bind a stream to.
* \param streams an array of audio streams to bind.
+14 -14
View File
@@ -106,7 +106,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardText(const char *text);
/**
* Get UTF-8 text from the clipboard.
*
* This functions returns an empty string if there was not enough memory left
* This function returns an empty string if there is not enough memory left
* for a copy of the clipboard's content.
*
* \returns the clipboard text on success or an empty string on failure; call
@@ -155,7 +155,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetPrimarySelectionText(const char *text);
/**
* Get UTF-8 text from the primary selection.
*
* This functions returns an empty string if there was not enough memory left
* This function returns an empty string if there is not enough memory left
* for a copy of the primary selection's content.
*
* \returns the primary selection text on success or an empty string on
@@ -194,15 +194,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
* clipboard is cleared or new data is set. The clipboard is automatically
* cleared in SDL_Quit().
*
* \param userdata a pointer to provided user data.
* \param userdata a pointer to the provided user data.
* \param mime_type the requested mime-type.
* \param size a pointer filled in with the length of the returned data.
* \returns a pointer to the data for the provided mime-type. Returning NULL
* or setting length to 0 will cause no data to be sent to the
* or setting the length to 0 will cause no data to be sent to the
* "receiver". It is up to the receiver to handle this. Essentially
* returning no data is more or less undefined behavior and may cause
* breakage in receiving applications. The returned data will not be
* freed so it needs to be retained and dealt with internally.
* freed, so it needs to be retained and dealt with internally.
*
* \since This function is available since SDL 3.2.0.
*
@@ -211,10 +211,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size);
/**
* Callback function that will be called when the clipboard is cleared, or new
* Callback function that will be called when the clipboard is cleared, or when new
* data is set.
*
* \param userdata a pointer to provided user data.
* \param userdata a pointer to the provided user data.
*
* \since This function is available since SDL 3.2.0.
*
@@ -231,7 +231,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
* respond with the data for the requested mime-type.
*
* The size of text data does not include any terminator, and the text does
* not need to be null terminated (e.g. you can directly copy a portion of a
* not need to be null-terminated (e.g., you can directly copy a portion of a
* document).
*
* \param callback a function pointer to the function that provides the
@@ -239,7 +239,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
* \param cleanup a function pointer to the function that cleans up the
* clipboard data.
* \param userdata an opaque pointer that will be forwarded to the callbacks.
* \param mime_types a list of mime-types that are being offered.
* \param mime_types a list of mime-types that are being offered. SDL copies the given list.
* \param num_mime_types the number of mime-types in the mime_types list.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
@@ -269,10 +269,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback
extern SDL_DECLSPEC bool SDLCALL SDL_ClearClipboardData(void);
/**
* Get the data from clipboard for a given mime type.
* Get the data from the clipboard for a given mime type.
*
* The size of text data does not include the terminator, but the text is
* guaranteed to be null terminated.
* guaranteed to be null-terminated.
*
* \param mime_type the mime type to read from the clipboard.
* \param size a pointer filled in with the length of the returned data.
@@ -292,8 +292,8 @@ extern SDL_DECLSPEC void * SDLCALL SDL_GetClipboardData(const char *mime_type, s
/**
* Query whether there is data in the clipboard for the provided mime type.
*
* \param mime_type the mime type to check for data for.
* \returns true if there exists data in clipboard for the provided mime type,
* \param mime_type the mime type to check for data.
* \returns true if data exists in the clipboard for the provided mime type,
* false if it does not.
*
* \threadsafety This function should only be called on the main thread.
@@ -310,7 +310,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardData(const char *mime_type);
*
* \param num_mime_types a pointer filled with the number of mime types, may
* be NULL.
* \returns a null terminated array of strings with mime types, or NULL on
* \returns a null-terminated array of strings with mime types, or NULL on
* failure; call SDL_GetError() for more information. This should be
* freed with SDL_free() when it is no longer needed.
*
+1 -1
View File
@@ -1549,7 +1549,7 @@ typedef struct SDL_GPUSamplerCreateInfo
typedef struct SDL_GPUVertexBufferDescription
{
Uint32 slot; /**< The binding slot of the vertex buffer. */
Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */
Uint32 pitch; /**< The size of a single element + the offset between elements. */
SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */
Uint32 instance_step_rate; /**< Reserved for future use. Must be set to 0. */
} SDL_GPUVertexBufferDescription;
+1 -1
View File
@@ -208,7 +208,7 @@ typedef enum SDL_Scancode
SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
* keyboards have over ANSI ones,
* located between left shift and Y.
* located between left shift and Z.
* Produces GRAVE ACCENT and TILDE in a
* US or UK Mac layout, REVERSE SOLIDUS
* (backslash) and VERTICAL LINE in a
+1 -1
View File
@@ -62,7 +62,7 @@ extern "C" {
*
* \since This macro is available since SDL 3.2.0.
*/
#define SDL_MICRO_VERSION 18
#define SDL_MICRO_VERSION 20
/**
* This macro turns the version numbers into a numeric value.
@@ -111,6 +111,9 @@ typedef unsigned int uintptr_t;
# define SDL_DISABLE_AVX 1
#endif
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
/* This can be disabled to avoid C runtime dependencies and manifest requirements */
#ifndef HAVE_LIBC
#define HAVE_LIBC 1
@@ -122,8 +125,6 @@ typedef unsigned int uintptr_t;
#define HAVE_LIMITS_H 1
#define HAVE_MATH_H 1
#define HAVE_SIGNAL_H 1
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
@@ -153,7 +154,6 @@ typedef unsigned int uintptr_t;
#define HAVE_STRCMP 1
#define HAVE_STRNCMP 1
#define HAVE_STRPBRK 1
#define HAVE_VSSCANF 1
#define HAVE_VSNPRINTF 1
#define HAVE_ACOS 1
#define HAVE_ASIN 1
@@ -211,10 +211,7 @@ typedef unsigned int uintptr_t;
#if _MSC_VER >= 1400
#define HAVE__FSEEKI64 1
#endif
#endif /* _MSC_VER */
#else
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#endif /* _MSC_VER */
#endif
/* Enable various audio drivers */
+14 -4
View File
@@ -1153,7 +1153,10 @@ 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));
SDL_assert(stream->src_spec.format != SDL_AUDIO_UNKNOWN);
const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
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.
@@ -1195,6 +1198,8 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &outspec, NULL, NULL));
SDL_assert(stream->src_spec.format != SDL_AUDIO_UNKNOWN);
/* this will hold a lock on `stream` while getting. We don't explicitly lock the streams
for iterating here because the binding linked list can only change while the device lock is held.
(we _do_ lock the stream during binding/unbinding to make sure that two threads can't try to bind
@@ -1330,6 +1335,7 @@ bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device)
SDL_assert(stream->src_spec.format == ((logdev->postmix || (logdev->gain != 1.0f)) ? SDL_AUDIO_F32 : device->spec.format));
SDL_assert(stream->src_spec.channels == device->spec.channels);
SDL_assert(stream->src_spec.freq == device->spec.freq);
SDL_assert(stream->dst_spec.format != SDL_AUDIO_UNKNOWN);
void *final_buf = output_buffer;
@@ -1975,10 +1981,6 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre
} else if (logdev->simplified) {
result = SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream");
} else {
// !!! FIXME: We'll set the device's side's format below, but maybe we should refuse to bind a stream if the app's side doesn't have a format set yet.
// !!! FIXME: Actually, why do we allow there to be an invalid format, again?
// make sure start of list is sane.
SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL));
@@ -2013,9 +2015,17 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre
if (result) {
// Now that everything is verified, chain everything together.
const bool recording = device->recording;
for (int i = 0; i < num_streams; i++) {
SDL_AudioStream *stream = streams[i];
if (stream) { // shouldn't be NULL, but just in case...
// if the stream never had its non-device-end format set, just set it to the device end's format.
if (recording && (stream->dst_spec.format == SDL_AUDIO_UNKNOWN)) {
SDL_copyp(&stream->dst_spec, &device->spec);
} else if (!recording && (stream->src_spec.format == SDL_AUDIO_UNKNOWN)) {
SDL_copyp(&stream->src_spec, &device->spec);
}
stream->bound_device = logdev;
stream->prev_binding = NULL;
stream->next_binding = logdev->bound_streams;
+4
View File
@@ -537,8 +537,10 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const U
// behavior. However, the compiler support for this pragma is bad.
#if defined(__clang__)
#if __clang_major__ >= 12
#if defined(__aarch64__)
#pragma STDC FENV_ACCESS ON
#endif
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (on)
#elif defined(__GNUC__)
@@ -814,8 +816,10 @@ static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samp
#if defined(__clang__)
#if __clang_major__ >= 12
#if defined(__aarch64__)
#pragma STDC FENV_ACCESS DEFAULT
#endif
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (off)
#elif defined(__GNUC__)
+2 -2
View File
@@ -2114,8 +2114,8 @@ bool SDL_LoadWAV_IO(SDL_IOStream *src, bool closeio, SDL_AudioSpec *spec, Uint8
result = WaveLoad(src, &file, spec, audio_buf, audio_len);
if (!result) {
SDL_free(*audio_buf);
audio_buf = NULL;
audio_len = 0;
*audio_buf = NULL;
*audio_len = 0;
}
// Cleanup
+1 -1
View File
@@ -114,7 +114,7 @@ static bool PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
} else {
rc = sceAudioOutputPannedBlocking(device->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, (void *) buffer);
}
return (rc == 0);
return (rc >= 0);
}
static bool PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
+1 -1
View File
@@ -814,7 +814,7 @@ static void ANDROIDCAMERA_Deinitialize(void)
static bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl)
{
// !!! FIXME: slide this off into a subroutine
// system libraries are in android-24 and later; we currently target android-16 and later, so check if they exist at runtime.
// system libraries are in android-24 and later; we currently target android-21 and later, so check if they exist at runtime.
void *libcamera2 = dlopen("libcamera2ndk.so", RTLD_NOW | RTLD_LOCAL);
if (!libcamera2) {
SDL_Log("CAMERA: libcamera2ndk.so can't be loaded: %s", dlerror());
+4 -4
View File
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,2,18,0
PRODUCTVERSION 3,2,18,0
FILEVERSION 3,2,20,0
PRODUCTVERSION 3,2,20,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "3, 2, 18, 0\0"
VALUE "FileVersion", "3, 2, 20, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL3.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "3, 2, 18, 0\0"
VALUE "ProductVersion", "3, 2, 20, 0\0"
END
END
BLOCK "VarFileInfo"
+3 -3
View File
@@ -2248,14 +2248,14 @@ void SDL_DrawGPUIndexedPrimitivesIndirect(
void SDL_EndGPURenderPass(
SDL_GPURenderPass *render_pass)
{
CommandBufferCommonHeader *commandBufferCommonHeader;
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
if (render_pass == NULL) {
SDL_InvalidParamError("render_pass");
return;
}
CommandBufferCommonHeader *commandBufferCommonHeader;
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
if (RENDERPASS_DEVICE->debug_mode) {
CHECK_RENDERPASS
}
+6 -5
View File
@@ -1194,7 +1194,6 @@ struct D3D12UniformBuffer
D3D12Buffer *buffer;
Uint32 writeOffset;
Uint32 drawOffset;
Uint32 currentBlockSize;
};
// Forward function declarations
@@ -1441,6 +1440,8 @@ static void D3D12_INTERNAL_ReleaseTextureContainer(
container->textures[i]);
}
SDL_DestroyProperties(container->header.info.props);
// Containers are just client handles, so we can destroy immediately
if (container->debugName) {
SDL_free(container->debugName);
@@ -4496,7 +4497,6 @@ static D3D12UniformBuffer *D3D12_INTERNAL_AcquireUniformBufferFromPool(
SDL_UnlockMutex(renderer->acquireUniformBufferLock);
uniformBuffer->currentBlockSize = 0;
uniformBuffer->drawOffset = 0;
uniformBuffer->writeOffset = 0;
@@ -4535,6 +4535,7 @@ static void D3D12_INTERNAL_PushUniformData(
Uint32 length)
{
D3D12UniformBuffer *uniformBuffer;
Uint32 blockSize;
if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
@@ -4559,13 +4560,13 @@ static void D3D12_INTERNAL_PushUniformData(
return;
}
uniformBuffer->currentBlockSize =
blockSize =
D3D12_INTERNAL_Align(
length,
256);
// If there is no more room, acquire a new uniform buffer
if (uniformBuffer->writeOffset + uniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
if (uniformBuffer->writeOffset + blockSize >= UNIFORM_BUFFER_SIZE) {
ID3D12Resource_Unmap(
uniformBuffer->buffer->handle,
0,
@@ -4595,7 +4596,7 @@ static void D3D12_INTERNAL_PushUniformData(
data,
length);
uniformBuffer->writeOffset += uniformBuffer->currentBlockSize;
uniformBuffer->writeOffset += blockSize;
if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
commandBuffer->needVertexUniformBufferBind[slotIndex] = true;
+1
View File
@@ -888,6 +888,7 @@ static void METAL_INTERNAL_DestroyTextureContainer(
container->textures[i]->handle = nil;
SDL_free(container->textures[i]);
}
SDL_DestroyProperties(container->header.info.props);
if (container->debugName != NULL) {
SDL_free(container->debugName);
}
+35 -13
View File
@@ -1108,6 +1108,7 @@ typedef struct VulkanCommandBuffer
VulkanFenceHandle *inFlightFence;
bool autoReleaseFence;
bool swapchainRequested;
bool isDefrag; // Whether this CB was created for defragging
} VulkanCommandBuffer;
@@ -1277,13 +1278,20 @@ static inline const char *VkErrorMessages(VkResult code)
#undef ERR_TO_STR
}
#define SET_ERROR_AND_RETURN(fmt, msg, ret) \
#define SET_ERROR(fmt, msg) \
do { \
if (renderer->debugMode) { \
SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
} \
SDL_SetError((fmt), (msg)); \
return ret; \
} while (0)
#define SET_STRING_ERROR(msg) SET_ERROR("%s", msg)
#define SET_ERROR_AND_RETURN(fmt, msg, ret) \
do { \
SET_ERROR(fmt, msg); \
return ret; \
} while (0)
#define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
@@ -6951,6 +6959,8 @@ static void VULKAN_ReleaseTexture(
VULKAN_INTERNAL_ReleaseTexture(renderer, vulkanTextureContainer->textures[i]);
}
SDL_DestroyProperties(vulkanTextureContainer->header.info.props);
// Containers are just client handles, so we can destroy immediately
if (vulkanTextureContainer->debugName != NULL) {
SDL_free(vulkanTextureContainer->debugName);
@@ -8592,7 +8602,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
dynamicOffsetCount,
dynamicOffsets);
commandBuffer->needNewVertexUniformOffsets = false;
commandBuffer->needNewComputeUniformOffsets = false;
}
static void VULKAN_DispatchCompute(
@@ -9925,6 +9935,14 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false);
}
// The command buffer is flagged for cleanup when the swapchain is requested as a cleanup timing mechanism
vulkanCommandBuffer->swapchainRequested = true;
if (window->flags & SDL_WINDOW_HIDDEN) {
// Edge case, texture is filled in with NULL but not an error
return true;
}
// If window data marked as needing swapchain recreate, try to recreate
if (windowData->needsSwapchainRecreate) {
Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
@@ -9942,13 +9960,6 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
}
}
if (swapchainTextureWidth) {
*swapchainTextureWidth = windowData->width;
}
if (swapchainTextureHeight) {
*swapchainTextureHeight = windowData->height;
}
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
if (block) {
// If we are blocking, just wait for the fence!
@@ -10000,6 +10011,14 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
}
}
if (swapchainTextureWidth) {
*swapchainTextureWidth = windowData->width;
}
if (swapchainTextureHeight) {
*swapchainTextureHeight = windowData->height;
}
swapchainTextureContainer = &windowData->textureContainers[swapchainImageIndex];
// We need a special execution dependency with pWaitDstStageMask or image transition can start before acquire finishes
@@ -10377,6 +10396,7 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
commandBuffer->presentDataCount = 0;
commandBuffer->waitSemaphoreCount = 0;
commandBuffer->signalSemaphoreCount = 0;
commandBuffer->swapchainRequested = false;
// Reset defrag state
@@ -10533,7 +10553,7 @@ static bool VULKAN_Submit(
VulkanTextureSubresource *swapchainTextureSubresource;
VulkanMemorySubAllocator *allocator;
bool performCleanups =
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->presentDataCount > 0) ||
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->swapchainRequested) ||
renderer->claimedWindowCount == 0;
SDL_LockMutex(renderer->submitLock);
@@ -11694,9 +11714,10 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->allowedFramesInFlight = 2;
if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
SET_STRING_ERROR("Failed to initialize Vulkan!");
SDL_free(renderer);
SDL_Vulkan_UnloadLibrary();
SET_STRING_ERROR_AND_RETURN("Failed to initialize Vulkan!", NULL);
return NULL;
}
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Vulkan");
@@ -11722,9 +11743,10 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
if (!VULKAN_INTERNAL_CreateLogicalDevice(
renderer)) {
SET_STRING_ERROR("Failed to create logical device!");
SDL_free(renderer);
SDL_Vulkan_UnloadLibrary();
SET_STRING_ERROR_AND_RETURN("Failed to create logical device!", NULL);
return NULL;
}
// FIXME: just move this into this function
+1 -1
View File
@@ -134,7 +134,6 @@ static wchar_t *utf8_to_wchar_t(const char *utf8)
* Use register_error_str(NULL) to free the error message completely. */
static void register_error_str(wchar_t **error_str, const char *msg)
{
free(*error_str);
#ifdef HIDAPI_USING_SDL_RUNTIME
/* Thread-safe error handling */
if (msg) {
@@ -143,6 +142,7 @@ static void register_error_str(wchar_t **error_str, const char *msg)
SDL_ClearError();
}
#else
free(*error_str);
*error_str = utf8_to_wchar_t(msg);
#endif
}
+1 -1
View File
@@ -311,7 +311,7 @@ void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id)
{
SDL_Event event;
if (!SDL_gamepads_initialized) {
if (!SDL_gamepads_initialized || SDL_IsJoystickBeingAdded()) {
return;
}
+5 -1
View File
@@ -2143,6 +2143,7 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
SDL_JoystickDriver *driver;
int device_index;
int player_index = -1;
bool is_gamepad;
SDL_AssertJoysticksLocked();
@@ -2177,9 +2178,12 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
}
}
// This might create an automatic gamepad mapping, so wait to send the event
is_gamepad = SDL_IsGamepad(instance_id);
SDL_joystick_being_added = false;
if (SDL_IsGamepad(instance_id)) {
if (is_gamepad) {
SDL_PrivateGamepadAdded(instance_id);
}
}
-1
View File
@@ -21,7 +21,6 @@
static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x0079, 0x181a ), k_eControllerType_PS3Controller, NULL }, // Venom Arcade Stick
{ MAKE_CONTROLLER_ID( 0x0079, 0x1844 ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x044f, 0xb315 ), k_eControllerType_PS3Controller, NULL }, // Firestorm Dual Analog 3
{ MAKE_CONTROLLER_ID( 0x044f, 0xd007 ), k_eControllerType_PS3Controller, NULL }, // Thrustmaster wireless 3-1
{ MAKE_CONTROLLER_ID( 0x046d, 0xcad1 ), k_eControllerType_PS3Controller, NULL }, // Logitech Chillstream
+16
View File
@@ -1651,6 +1651,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_v);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1665,6 +1667,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1672,11 +1676,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u);
if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
SDL_free(data->pixel_data);
SDL_free(data);
return SDL_SetError("Unsupported YUV colorspace");
}
} else if (data->nv12) {
@@ -1686,6 +1694,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1693,11 +1703,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u);
if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
SDL_free(data->pixel_data);
SDL_free(data);
return SDL_SetError("Unsupported YUV colorspace");
}
}
@@ -1709,6 +1723,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
+6 -1
View File
@@ -41,7 +41,12 @@
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
static char **get_environ_rtld(void)
{
char ***environ_rtld = (char ***)dlsym(RTLD_DEFAULT, "environ");
return environ_rtld ? *environ_rtld : NULL;
}
#define environ (get_environ_rtld())
#else
extern char **environ;
#endif
+7
View File
@@ -1478,6 +1478,13 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int);
#endif /* NO_MALLOC_STATS */
#ifndef LACKS_ERRNO_H
#include <errno.h> /* for MALLOC_FAILURE_ACTION */
#else /* LACKS_ERRNO_H */
#ifndef EINVAL
#define EINVAL 22
#endif
#ifndef ENOMEM
#define ENOMEM 12
#endif
#endif /* LACKS_ERRNO_H */
#ifdef DEBUG
#if ABORT_ON_ASSERT_FAILURE
+10 -4
View File
@@ -42,6 +42,10 @@ void SDL_CancelClipboardData(Uint32 sequence)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return;
}
if (sequence && sequence != _this->clipboard_sequence) {
// This clipboard data was already canceled
return;
@@ -62,6 +66,10 @@ bool SDL_SaveClipboardMimeTypes(const char **mime_types, size_t num_mime_types)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return SDL_UninitializedVideo();
}
SDL_FreeClipboardMimeTypes(_this);
if (mime_types && num_mime_types > 0) {
@@ -234,13 +242,11 @@ bool SDL_HasClipboardData(const char *mime_type)
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
SDL_UninitializedVideo();
return false;
return SDL_UninitializedVideo();
}
if (!mime_type) {
SDL_InvalidParamError("mime_type");
return false;
return SDL_InvalidParamError("mime_type");
}
if (_this->HasClipboardData) {
+1 -1
View File
@@ -1247,7 +1247,7 @@ bool SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surfac
// Clip again
SDL_GetRectIntersection(clip_rect, &final_dst, &final_dst);
if (final_dst.w == 0 || final_dst.h == 0 ||
if (final_dst.w <= 0 || final_dst.h <= 0 ||
final_src.w < 0 || final_src.h < 0) {
// No-op.
return true;
+20 -14
View File
@@ -1199,21 +1199,27 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
ScheduleContextUpdates(_data);
/* isZoomed always returns true if the window is not resizable
* and fullscreen windows are considered zoomed.
/* The OS can resize the window automatically if the display density
* changes while the window is miniaturized or hidden.
*/
if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed] &&
!(window->flags & SDL_WINDOW_FULLSCREEN) && ![self isInFullscreenSpace]) {
zoomed = YES;
} else {
zoomed = NO;
}
if (!zoomed) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
} else {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
if ([self windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) {
[nswindow miniaturize:nil];
if ([nswindow isVisible])
{
/* isZoomed always returns true if the window is not resizable
* and fullscreen windows are considered zoomed.
*/
if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed] &&
!(window->flags & SDL_WINDOW_FULLSCREEN) && ![self isInFullscreenSpace]) {
zoomed = YES;
} else {
zoomed = NO;
}
if (!zoomed) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
} else {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
if ([self windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) {
[nswindow miniaturize:nil];
}
}
}
+11 -13
View File
@@ -215,32 +215,32 @@ static void EnsurePopupPositionIsValid(SDL_Window *window, int *x, int *y)
int adj_count = 0;
/* Per the xdg-positioner spec, child popup windows must intersect or at
* least be partially adjacent to the parent window.
* least be partially adjoining the parent window.
*
* Failure to ensure this on a compositor that enforces this restriction
* can result in behavior ranging from the window being spuriously closed
* to a protocol violation.
*/
if (*x + window->w < 0) {
if (*x + window->w <= 0) {
*x = -window->w;
++adj_count;
}
if (*y + window->h < 0) {
if (*y + window->h <= 0) {
*y = -window->h;
++adj_count;
}
if (*x > window->parent->w) {
if (*x >= window->parent->w) {
*x = window->parent->w;
++adj_count;
}
if (*y > window->parent->h) {
if (*y >= window->parent->h) {
*y = window->parent->h;
++adj_count;
}
/* If adjustment was required on the x and y axes, the popup is aligned with
* the parent corner-to-corner and is neither overlapping nor adjacent, so it
* must be nudged by 1 to be considered adjacent.
* the parent corner-to-corner and is neither overlapping nor adjoining, so it
* must be nudged by 1 to be considered adjoining.
*/
if (adj_count > 1) {
*x += *x < 0 ? 1 : -1;
@@ -2116,12 +2116,6 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
wind->server_decoration = NULL;
}
// Be sure to detach after this is done, otherwise ShowWindow crashes!
if (wind->shell_surface_type != WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
wl_surface_attach(wind->surface, NULL, 0, 0);
wl_surface_commit(wind->surface);
}
// Clean up the export handle.
if (wind->exported) {
zxdg_exported_v2_destroy(wind->exported);
@@ -2159,6 +2153,10 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
// Attach a null buffer to unmap the surface.
wl_surface_attach(wind->surface, NULL, 0, 0);
wl_surface_commit(wind->surface);
SDL_zero(wind->shell_surface);
wind->show_hide_sync_required = true;
struct wl_callback *cb = wl_display_sync(_this->internal->display);
+3 -7
View File
@@ -194,7 +194,7 @@ static bool X11_KeyRepeat(Display *display, XEvent *event)
return d.found;
}
static bool X11_IsWheelEvent(Display *display, int button, int *xticks, int *yticks)
bool X11_IsWheelEvent(int button, int *xticks, int *yticks)
{
/* according to the xlib docs, no specific mouse wheel events exist.
However, the defacto standard is that the vertical wheel is X buttons
@@ -1016,8 +1016,6 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time)
{
SDL_Window *window = windowdata->window;
const SDL_VideoData *videodata = _this->internal;
Display *display = videodata->display;
int xticks = 0, yticks = 0;
Uint64 timestamp = X11_GetEventTimestamp(time);
@@ -1031,7 +1029,7 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S
SDL_SendMouseMotion(timestamp, window, mouseID, false, x, y);
}
if (X11_IsWheelEvent(display, button, &xticks, &yticks)) {
if (X11_IsWheelEvent(button, &xticks, &yticks)) {
SDL_SendMouseWheel(timestamp, window, mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
} else {
bool ignore_click = false;
@@ -1063,8 +1061,6 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S
void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time)
{
SDL_Window *window = windowdata->window;
const SDL_VideoData *videodata = _this->internal;
Display *display = videodata->display;
// The X server sends a Release event for each Press for wheels. Ignore them.
int xticks = 0, yticks = 0;
Uint64 timestamp = X11_GetEventTimestamp(time);
@@ -1072,7 +1068,7 @@ void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata,
#ifdef DEBUG_XEVENTS
SDL_Log("window 0x%lx: ButtonRelease (X11 button = %d)", windowdata->xwindow, button);
#endif
if (!X11_IsWheelEvent(display, button, &xticks, &yticks)) {
if (!X11_IsWheelEvent(button, &xticks, &yticks)) {
if (button > 7) {
// see explanation at case ButtonPress
button -= (8 - SDL_BUTTON_X1);
+1
View File
@@ -36,5 +36,6 @@ extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wind
extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
extern bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, bool force_new_result);
extern bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y);
extern bool X11_IsWheelEvent(int button, int *xticks, int *yticks);
#endif // SDL_x11events_h_
+8
View File
@@ -425,6 +425,14 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
} else {
// Otherwise assume a regular mouse
SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event);
int x_ticks = 0, y_ticks = 0;
/* Discard wheel events from "Master" devices to avoid duplicates,
* as coarse wheel events are stateless and can't be deduplicated.
*/
if (xev->deviceid != xev->sourceid && X11_IsWheelEvent(button, &x_ticks, &y_ticks)) {
break;
}
if (down) {
X11_HandleButtonPress(_this, windowdata, (SDL_MouseID)xev->sourceid, button,
+44
View File
@@ -989,6 +989,45 @@ static int SDLCALL surface_testBlitInvalid(void *arg)
return TEST_COMPLETED;
}
static int SDLCALL surface_testBlitsWithBadCoordinates(void *arg)
{
const SDL_Rect rect[8] = {
{ SDL_MAX_SINT32, 0, 2, 2 },
{ 0, SDL_MAX_SINT32, 2, 2 },
{ 0, 0, SDL_MAX_SINT32, 2 },
{ 0, 0, 2, SDL_MAX_SINT32 },
{ SDL_MIN_SINT32, 0, 2, 2 },
{ 0, SDL_MIN_SINT32, 2, 2 },
{ 0, 0, SDL_MIN_SINT32, 2 },
{ 0, 0, 2, SDL_MIN_SINT32 }
};
SDL_Surface *s;
bool result;
int i;
s = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA8888);
SDLTest_AssertCheck(s != NULL, "Check surface creation");
for (i = 0; i < 8; i++) {
result = SDL_BlitSurface(s, NULL, s, &rect[i]);
SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, NULL, valid, &rect), result = %s", result ? "true" : "false");
result = SDL_BlitSurface(s, &rect[i], s, NULL);
SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, &rect, valid, NULL), result = %s", result ? "true" : "false");
result = SDL_BlitSurfaceScaled(s, NULL, s, &rect[i], SDL_SCALEMODE_NEAREST);
SDLTest_AssertCheck(result == true, "SDL_BlitSurfaceScaled(valid, NULL, valid, &rect, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
result = SDL_BlitSurfaceScaled(s, &rect[i], s, NULL, SDL_SCALEMODE_NEAREST);
SDLTest_AssertCheck(result == true, "SDL_BlitSurfaceScaled(valid, &rect, valid, NULL, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
}
SDL_DestroySurface(s);
return TEST_COMPLETED;
}
static int SDLCALL surface_testOverflow(void *arg)
{
char buf[1024];
@@ -1664,6 +1703,10 @@ static const SDLTest_TestCaseReference surfaceTestBlitInvalid = {
surface_testBlitInvalid, "surface_testBlitInvalid", "Tests blitting routines with invalid surfaces.", TEST_ENABLED
};
static const SDLTest_TestCaseReference surfaceTestBlitsWithBadCoordinates = {
surface_testBlitsWithBadCoordinates, "surface_testBlitsWithBadCoordinates", "Test blitting routines with bad coordinates.", TEST_ENABLED
};
static const SDLTest_TestCaseReference surfaceTestOverflow = {
surface_testOverflow, "surface_testOverflow", "Test overflow detection.", TEST_ENABLED
};
@@ -1713,6 +1756,7 @@ static const SDLTest_TestCaseReference *surfaceTests[] = {
&surfaceTestBlitBlendMod,
&surfaceTestBlitBlendMul,
&surfaceTestBlitInvalid,
&surfaceTestBlitsWithBadCoordinates,
&surfaceTestOverflow,
&surfaceTestFlip,
&surfaceTestPalette,