Compare commits

..

26 Commits

Author SHA1 Message Date
Ryan C. Gordon d6d81eeac3
Merge 9dc6c6e4d4 into 038a3806eb 2025-06-22 18:11:33 +02:00
Sam Lantinga 038a3806eb Fixed Nintendo Switch Pro thumbstick calibration
Fixes https://github.com/libsdl-org/SDL/issues/13246
2025-06-21 19:55:05 -07:00
Sam Lantinga e6c2649afc Updated testffmpeg for ffmpeg 7.1 2025-06-21 08:48:40 -07:00
Sasha Szpakowski e80d084766 expose events originating from a live-resize set the data1 field to 1.
Fixes #13243.
2025-06-21 07:33:25 -07:00
Josh Dowell 6aedc488d3 win32: Invalidate window message mouse button flags when reading buttons from raw input or GameInput
SDL2 would set a high bit in the mouse button flags to indicate when raw input had been read from, without this, if you hold down a mouse button and left raw input mode (leaving relative mode) the button would remain partially stuck, and would require two clicks to start producing mouse down events again.
SDL3's raw input code was refactored to not use the mouse button flags, but forgot to invalidate the flags, causing this bug to manifest.
2025-06-21 07:28:14 -07:00
Ozkan Sezer 81e3066303 hidapi/libusb: disable C5287 warning in MSVC builds
A quick search implies that it is a bogus warning:
https://www.google.com/search?q=visual+studio+C5287
2025-06-21 07:15:53 -07:00
Sam Lantinga 7d9fd48557 alsa: recover from snd_pcm_avail() returning -EPIPE 2025-06-20 16:33:30 -07:00
Sam Lantinga e68f5ca99a alsa: use udev if available instead of a hotplug thread
This makes detecting audio device changes more responsive.
2025-06-20 19:19:31 -04:00
Sam Lantinga 051ce0ff89 alsa: fixed disconnecting the microphone when opened
Some devices take some time for data to become available, so we'll keep waiting as long as necessary for them to provide data.
2025-06-20 19:19:31 -04:00
Wohlstand 5fcc83d93b Vita Render: Limit the scope of cliprect to viewport
Don't allow cliprect be larger than viewport's scope

(cherry picked from commit 6701f938f7)

# Conflicts:
#	src/render/vitagxm/SDL_render_vita_gxm.c
2025-06-20 14:51:16 -07:00
Wohlstand 1bd5110ff0 Vita: Fixed absence of clipping when viewport is set
#13034

(cherry picked from commit 1c09a7117a)

# Conflicts:
#	src/render/vitagxm/SDL_render_vita_gxm.c
#	src/render/vitagxm/SDL_render_vita_gxm_types.h
2025-06-20 14:51:16 -07:00
Ryan C. Gordon eb04219efe
audio: Enumerating audio devices will skip zombie devices still in the hash. 2025-06-20 17:37:39 -04:00
SDL Wiki Bot d06b6e42d2 Sync SDL3 wiki -> header
[ci skip]
2025-06-20 21:02:26 +00:00
Sam Lantinga c19ad189dc Clarify that SDL_GetAudioStreamDevice() returns the logical device. 2025-06-20 14:01:16 -07:00
Sam Lantinga 7882e60f0e Don't log an error for disconnected audio devices 2025-06-20 11:05:08 -07:00
Lilian Gimenez e4e29b8601 Fix support for F21 to F24 scancodes on Linux 2025-06-20 09:06:57 -07:00
Sam Lantinga d7939abf42 Use consistent style for pointer declarations and casts 2025-06-18 10:03:44 -07:00
Frank Praznik 390fe65323
test: Fix a window parenting bug in testmodal 2025-06-18 09:26:09 -04:00
Frank Praznik ca9b7c8ea3
video: Explicitly disallow setting the parent of a window to itself
Doing so causes a cycle in the window hierarchy tree graph, which leads to infinite recursion when destroying the windows.
2025-06-18 09:26:08 -04:00
Ryan C. Gordon c04624972e
alsa: Simplify ALSA_WaitDevice.
- Check for specific availability instead of waiting for "device ready."
- Don't use snd_pcm_wait, just use a simple SDL_Delay (nothing to recover).
- Fixed SDL_max call that should have been SDL_min (now using SDL_clamp).
- ALSA_RecordDevice() now returns 0 if no availability, which kicks us back
  to WaitDevice to try again, as an extra safety check.
2025-06-17 20:40:00 -04:00
Ryan C. Gordon b4ac5f43f5
include: Fixed copy/paste error in endian-specific SDL_Read function docs. 2025-06-17 16:41:24 -04:00
Ryan C. Gordon 3896b1b3f4
wikiheaders: Let each subproject specify how to find their property symbols. 2025-06-17 16:41:24 -04:00
Sam Lantinga efed3c63b3 Added support for an alternate version of the Vader 4 Pro 2025-06-17 10:02:10 -07:00
Sam Lantinga d6bae53341 Added support for an alternate version of the Vader 4 Pro 2025-06-17 08:07:12 -07:00
Sam Lantinga f62c982bcf Reverted Accelerometer and Gyro displays to throttled display (10hz)
Also made accelerometer threshold for drift calibration more lenient for very noisy accelerometers.

The testcontroller tool could eventually be used to come up with a better way to profile an IMU's "stationary" noise so that this threshold can be as tight as necessary for the sake of automatic drift calibration.

(thanks @HilariousCow!)
2025-06-16 11:14:22 -07:00
Sam Lantinga b833c618a9 Improved reliability detecting FlyDigi Vader controllers 2025-06-16 11:07:50 -07:00
124 changed files with 627 additions and 448 deletions

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

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';
@ -110,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';
@ -1366,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) {

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.

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 */

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

@ -1415,6 +1415,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;
@ -1430,8 +1431,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.
}
@ -1446,10 +1453,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);

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__)
@ -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!
@ -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();
@ -1460,12 +1520,14 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevi
*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

@ -371,10 +371,10 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
/* 188, 0x0bc */ SDL_SCANCODE_F18, // XF86Launch9
/* 189, 0x0bd */ SDL_SCANCODE_F19, // NoSymbol
/* 190, 0x0be */ SDL_SCANCODE_F20, // XF86AudioMicMute
/* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadToggle
/* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOn
/* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOff
/* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
/* 191, 0x0bf */ SDL_SCANCODE_F21, // XF86TouchpadToggle
/* 192, 0x0c0 */ SDL_SCANCODE_F22, // XF86TouchpadOn
/* 193, 0x0c1 */ SDL_SCANCODE_F23, // XF86TouchpadOff
/* 194, 0x0c2 */ SDL_SCANCODE_F24, // NoSymbol
/* 195, 0x0c3 */ SDL_SCANCODE_MODE, // Mode_switch
/* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
/* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, // NoSymbol

View File

@ -71,6 +71,11 @@ extern "C" {
#define DETACH_KERNEL_DRIVER
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:5287) /* operands are different enum types */
#endif
/* Uncomment to enable the retrieval of Usage and Usage Page in
hid_enumerate(). Warning, on platforms different from FreeBSD
this is very invasive as it requires the detach
@ -2144,6 +2149,10 @@ uint16_t get_usb_code_for_current_locale(void)
return 0x0;
}
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#ifdef __cplusplus
}
#endif

View File

@ -841,6 +841,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
case 80:
case 81:
case 85:
case 105:
// Vader series of controllers have C/Z buttons
SDL_strlcat(mapping_string, "misc2:b15,misc3:b16,", sizeof(mapping_string));
break;

View File

@ -95,19 +95,18 @@ static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
{
SDL_DriverFlydigi_Context *ctx = (SDL_DriverFlydigi_Context *)device->context;
for (int attempt = 0; ctx->deviceID == 0 && attempt < 3; ++attempt) {
// Detecting the Vader 2 can take over 1000 read retries, so be generous here
for (int attempt = 0; ctx->deviceID == 0 && attempt < 30; ++attempt) {
const Uint8 request[] = { FLYDIGI_CMD_REPORT_ID, FLYDIGI_GET_INFO_COMMAND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int size = SDL_hid_write(device->dev, request, sizeof(request));
if (size < 0) {
break;
}
// This write will occasionally return -1, so ignore failure here and try again
(void)SDL_hid_write(device->dev, request, sizeof(request));
// Read the reply
for (int i = 0; i < 100; ++i) {
SDL_Delay(1);
Uint8 data[USB_PACKET_LENGTH];
size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0);
int size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0);
if (size < 0) {
break;
}
@ -211,6 +210,7 @@ static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
ctx->sensor_timestamp_step_ns = ctx->wireless ? SENSOR_INTERVAL_VADER4_PRO_DONGLE_NS : SENSOR_INTERVAL_VADER_PRO4_WIRED_NS;
break;
case 85:
case 105:
HIDAPI_SetDeviceName(device, "Flydigi Vader 4 Pro");
ctx->has_cz = true;
ctx->sensors_supported = true;
@ -218,6 +218,7 @@ static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
ctx->sensor_timestamp_step_ns = ctx->wireless ? SENSOR_INTERVAL_VADER4_PRO_DONGLE_NS : SENSOR_INTERVAL_VADER_PRO4_WIRED_NS;
break;
default:
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Unknown FlyDigi controller with ID %d, name '%s'", ctx->deviceID, device->name);
break;
}
}

View File

@ -979,7 +979,7 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
/* Stick calibration values are 12-bits each and are packed by bit
* For whatever reason the fields are in a different order for each stick
* Left: X-Max, Y-Max, X-Center, Y-Center, X-Min, Y-Min
* Right: X-Center, Y-Center, X-Min, Y-Min, X-Max, Y-Max
* Right: X-Center, Y-Center, X-Max, Y-Max, X-Min, Y-Min
*/
// Left stick
@ -993,10 +993,10 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
// Right stick
ctx->m_StickCalData[1].axis[0].sCenter = ((pRightStickCal[1] << 8) & 0xF00) | pRightStickCal[0]; // X Axis center
ctx->m_StickCalData[1].axis[1].sCenter = (pRightStickCal[2] << 4) | (pRightStickCal[1] >> 4); // Y Axis center
ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis min below center
ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis min below center
ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis max above center
ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis max above center
ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis max above center
ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis max above center
ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis min below center
ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis min below center
// Filter out any values that were uninitialized (0xFFF) in the SPI read
for (stick = 0; stick < 2; ++stick) {
@ -1109,14 +1109,17 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
{
sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter;
if (sRawValue >= 0) {
if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
}
static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
@ -1126,14 +1129,17 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt
sRawValue -= usJoystickCenter;
if (sRawValue >= 0) {
if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
}
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)

View File

@ -820,6 +820,35 @@ static SceGxmTextureAddrMode TranslateAddressMode(SDL_TextureAddressMode mode)
}
}
static void ClampCliprectToViewport(SDL_Rect *clip, const SDL_Rect *viewport)
{
int max_x_v, max_y_v, max_x_c, max_y_c;
if (clip->x < 0) {
clip->w += clip->x;
clip->x = 0;
}
if (clip->y < 0) {
clip->h += clip->y;
clip->y = 0;
}
max_x_c = clip->x + clip->w;
max_y_c = clip->y + clip->h;
max_x_v = viewport->x + viewport->w;
max_y_v = viewport->y + viewport->h;
if (max_x_c > max_x_v) {
clip->w -= (max_x_v - max_x_c);
}
if (max_y_c > max_y_v) {
clip->h -= (max_y_v - max_y_c);
}
}
static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
@ -862,9 +891,13 @@ static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd
data->drawstate.cliprect_enabled_dirty = false;
}
if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
const SDL_Rect *rect = &data->drawstate.cliprect;
set_clip_rectangle(data, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
if ((data->drawstate.cliprect_enabled || data->drawstate.viewport_is_set) && data->drawstate.cliprect_dirty) {
SDL_Rect rect;
SDL_copyp(&rect, &data->drawstate.cliprect);
if (data->drawstate.viewport_is_set) {
ClampCliprectToViewport(&rect, &data->drawstate.viewport);
}
set_clip_rectangle(data, rect.x, rect.y, rect.x + rect.w, rect.y + rect.h);
data->drawstate.cliprect_dirty = false;
}
@ -952,19 +985,30 @@ static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer)
static bool VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal;
int w, h;
StartDrawing(renderer);
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
int w, h;
SDL_GetWindowSizeInPixels(renderer->window, &w, &h);
} else {
float fw, fh;
if (!SDL_GetTextureSize(renderer->target, &fw, &fh)) {
w = data->drawstate.drawablew;
h = data->drawstate.drawableh;
} else {
w = (int)SDL_roundf(fw);
h = (int)SDL_roundf(fh);
}
}
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = true; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = true;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}
}
while (cmd) {
switch (cmd->command) {
@ -976,6 +1020,16 @@ static bool VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *
SDL_copyp(viewport, &cmd->data.viewport.rect);
data->drawstate.viewport_dirty = true;
data->drawstate.cliprect_dirty = true;
data->drawstate.viewport_is_set = viewport->x != 0 || viewport->y != 0 || viewport->w != data->drawstate.drawablew || viewport->h != data->drawstate.drawableh;
if (!data->drawstate.cliprect_enabled) {
if (data->drawstate.viewport_is_set) {
SDL_copyp(&data->drawstate.cliprect, viewport);
data->drawstate.cliprect.x = 0;
data->drawstate.cliprect.y = 0;
} else {
data->drawstate.cliprect_enabled_dirty = true;
}
}
}
break;
}
@ -983,9 +1037,15 @@ static bool VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *
case SDL_RENDERCMD_SETCLIPRECT:
{
const SDL_Rect *rect = &cmd->data.cliprect.rect;
const SDL_Rect *viewport = &data->drawstate.viewport;
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
data->drawstate.cliprect_enabled_dirty = true;
if (!data->drawstate.cliprect_enabled && data->drawstate.viewport_is_set) {
SDL_copyp(&data->drawstate.cliprect, viewport);
data->drawstate.cliprect.x = 0;
data->drawstate.cliprect.y = 0;
}
}
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {

View File

@ -105,6 +105,7 @@ typedef struct
{
SDL_Rect viewport;
bool viewport_dirty;
bool viewport_is_set;
SDL_Texture *texture;
SDL_Texture *target;
SDL_FColor color;

View File

@ -3672,6 +3672,10 @@ bool SDL_SetWindowParent(SDL_Window *window, SDL_Window *parent)
CHECK_WINDOW_NOT_POPUP(parent, false);
}
if (window == parent) {
return SDL_SetError("Cannot set the parent of a window to itself.");
}
if (!_this->SetWindowParent) {
return SDL_Unsupported();
}
@ -4135,7 +4139,7 @@ void SDL_OnWindowLiveResizeUpdate(SDL_Window *window)
SDL_IterateMainCallbacks(false);
} else {
// Send an expose event so the application can redraw
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 1, 0);
}
SDL_PumpEventMaintenance();

View File

@ -110,8 +110,7 @@ void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForAndroid[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME

View File

@ -161,8 +161,7 @@ void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
char const* const* Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForCocoa[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME

View File

@ -140,8 +140,7 @@ void KMSDRM_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
// members of the VkInstanceCreateInfo struct passed to
// vkCreateInstance().
/*********************************************************************/
char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForKMSDRM[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME

View File

@ -167,8 +167,7 @@ void UIKit_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
char const* const* UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForUIKit[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME

View File

@ -117,8 +117,7 @@ void VIVANTE_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
char const* const* VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForVivante[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME

View File

@ -701,6 +701,10 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL
float fAmount = (float)amount / WHEEL_DELTA;
SDL_SendMouseWheel(WIN_GetEventTimestamp(), window, mouseID, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL);
}
/* Invalidate the mouse button flags. If we don't do this then disabling raw input
will cause held down mouse buttons to persist when released. */
windowdata->mouse_button_flags = (WPARAM)-1;
}
}

View File

@ -279,6 +279,9 @@ static void GAMEINPUT_InitialMouseReading(WIN_GameInputData *data, SDL_Window *w
bool down = ((state.buttons & mask) != 0);
SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down);
}
// Invalidate mouse button flags
window->internal->mouse_button_flags = (WPARAM)-1;
}
}
@ -308,6 +311,9 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind
SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down);
}
}
// Invalidate mouse button flags
window->internal->mouse_button_flags = (WPARAM)-1;
}
if (delta.wheelX || delta.wheelY) {
float fAmountX = (float)delta.wheelX / WHEEL_DELTA;

View File

@ -110,8 +110,7 @@ void WIN_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
char const* const* WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForWin32[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME

View File

@ -144,8 +144,7 @@ void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
char const * const *X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
SDL_VideoData *videoData = _this->internal;
if (videoData->vulkan_xlib_xcb_library) {

View File

@ -1611,8 +1611,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
has_gyro = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_GYRO);
if (has_accel || has_gyro) {
const float gyro_sensor_rate = has_gyro ? SDL_GetGamepadSensorDataRate(gamepad, SDL_SENSOR_GYRO) : 0;
const int SENSOR_UPDATE_INTERVAL_MS = gyro_sensor_rate > 0.0f ? (int)( 1000.0f / gyro_sensor_rate ) : 100;
const int SENSOR_UPDATE_INTERVAL_MS = 100;
Uint64 now = SDL_GetTicks();
if (now >= ctx->last_sensor_update + SENSOR_UPDATE_INTERVAL_MS) {
@ -1622,6 +1621,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
if (has_gyro) {
SDL_GetGamepadSensorData(gamepad, SDL_SENSOR_GYRO, ctx->gyro_data, SDL_arraysize(ctx->gyro_data));
}
ctx->last_sensor_update = now;
}
if (has_accel) {
@ -1639,8 +1639,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
SDLTest_DrawString(ctx->renderer, x + center + 2.0f, y, text);
/* Display a smoothed version of the above for the sake of turntable tests */
/* Display the testcontroller tool's evaluation of drift. This is also useful to get an average rate of turn in calibrated turntable tests. */
if (ctx->gyro_drift_correction_data[0] != 0.0f && ctx->gyro_drift_correction_data[2] != 0.0f && ctx->gyro_drift_correction_data[2] != 0.0f )
{
y += ctx->button_height + 2.0f;
@ -1652,7 +1651,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
}
ctx->last_sensor_update = now;
}
}
SDL_free(mapping);

View File

@ -143,7 +143,7 @@ extern void DestroyGamepadButton(GamepadButton *ctx);
/* Gyro element Display */
/* If you want to calbirate against a known rotation (i.e. a turn table test) Increase ACCELEROMETER_NOISE_THRESHOLD to about 5, or drift correction will be constantly reset.*/
#define ACCELEROMETER_NOISE_THRESHOLD 0.125f
#define ACCELEROMETER_NOISE_THRESHOLD 0.5f
typedef struct Quaternion Quaternion;
typedef struct GyroDisplay GyroDisplay;

View File

@ -1409,11 +1409,13 @@ static void UpdateGamepadOrientation( Uint64 delta_time_ns )
static void HandleGamepadSensorEvent( SDL_Event* event )
{
if (!controller)
if (!controller) {
return;
}
if (controller->id != event->gsensor.which)
if (controller->id != event->gsensor.which) {
return;
}
if (event->gsensor.sensor == SDL_SENSOR_GYRO) {
HandleGamepadGyroEvent(event);

View File

@ -679,6 +679,16 @@ void SetupVulkanRenderProperties(VulkanVideoContext *context, SDL_PropertiesID p
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER, context->graphicsQueueFamilyIndex);
}
#if LIBAVUTIL_VERSION_MAJOR >= 59
static void AddQueueFamily(AVVulkanDeviceContext *ctx, int idx, int num, VkQueueFlagBits flags)
{
AVVulkanDeviceQueueFamily *entry = &ctx->qf[ctx->nb_qf++];
entry->idx = idx;
entry->num = num;
entry->flags = flags;
}
#endif /* LIBAVUTIL_VERSION_MAJOR */
void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceContext *ctx)
{
ctx->get_proc_addr = context->vkGetInstanceProcAddr;
@ -690,6 +700,12 @@ void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceCon
ctx->nb_enabled_inst_extensions = context->instanceExtensionsCount;
ctx->enabled_dev_extensions = context->deviceExtensions;
ctx->nb_enabled_dev_extensions = context->deviceExtensionsCount;
#if LIBAVUTIL_VERSION_MAJOR >= 59
AddQueueFamily(ctx, context->graphicsQueueFamilyIndex, context->graphicsQueueCount, VK_QUEUE_GRAPHICS_BIT);
AddQueueFamily(ctx, context->transferQueueFamilyIndex, context->transferQueueCount, VK_QUEUE_TRANSFER_BIT);
AddQueueFamily(ctx, context->computeQueueFamilyIndex, context->computeQueueCount, VK_QUEUE_COMPUTE_BIT);
AddQueueFamily(ctx, context->decodeQueueFamilyIndex, context->decodeQueueCount, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
#else
ctx->queue_family_index = context->graphicsQueueFamilyIndex;
ctx->nb_graphics_queues = context->graphicsQueueCount;
ctx->queue_family_tx_index = context->transferQueueFamilyIndex;
@ -700,6 +716,7 @@ void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceCon
ctx->nb_encode_queues = 0;
ctx->queue_family_decode_index = context->decodeQueueFamilyIndex;
ctx->nb_decode_queues = context->decodeQueueCount;
#endif /* LIBAVUTIL_VERSION_MAJOR */
}
static int CreateCommandBuffers(VulkanVideoContext *context, SDL_Renderer *renderer)

View File

@ -97,7 +97,7 @@ int main(int argc, char *argv[])
}
if (e.key.key == SDLK_M) {
if (SDL_SetWindowParent(w2, w2)) {
if (SDL_SetWindowParent(w2, w1)) {
if (SDL_SetWindowModal(w2, true)) {
SDL_SetWindowTitle(w2, "Modal Window");
}