Use a separate sensor watching function for gamepad events to avoid reliance on system sensor events and prevent a potential deadlock
This commit is contained in:
parent
70e43c150e
commit
20ea35138f
3 changed files with 53 additions and 33 deletions
|
@ -318,22 +318,6 @@ static void RecenterGamepad(SDL_Gamepad *gamepad)
|
|||
}
|
||||
}
|
||||
|
||||
/* SDL defines sensor orientation relative to the device natural
|
||||
orientation, so when it's changed orientation to be used as a
|
||||
gamepad, change the sensor orientation to match.
|
||||
*/
|
||||
static void AdjustSensorOrientation(SDL_Joystick *joystick, float *src, float *dst)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
dst[i] = 0.0f;
|
||||
for (j = 0; j < 3; ++j) {
|
||||
dst[i] += joystick->sensor_transform[i][j] * src[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Event filter to fire gamepad events from joystick ones
|
||||
*/
|
||||
|
@ -408,23 +392,6 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
|
|||
SDL_PushEvent(&deviceevent);
|
||||
}
|
||||
} break;
|
||||
case SDL_EVENT_SENSOR_UPDATE:
|
||||
{
|
||||
SDL_LockJoysticks();
|
||||
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
|
||||
if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == event->sensor.which) {
|
||||
float data[3];
|
||||
AdjustSensorOrientation(gamepad->joystick, event->sensor.data, data);
|
||||
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
|
||||
}
|
||||
if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == event->sensor.which) {
|
||||
float data[3];
|
||||
AdjustSensorOrientation(gamepad->joystick, event->sensor.data, data);
|
||||
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_GYRO, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
|
||||
}
|
||||
}
|
||||
SDL_UnlockJoysticks();
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -432,6 +399,52 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* SDL defines sensor orientation relative to the device natural
|
||||
orientation, so when it's changed orientation to be used as a
|
||||
gamepad, change the sensor orientation to match.
|
||||
*/
|
||||
static void AdjustSensorOrientation(SDL_Joystick *joystick, float *src, float *dst)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
dst[i] = 0.0f;
|
||||
for (j = 0; j < 3; ++j) {
|
||||
dst[i] += joystick->sensor_transform[i][j] * src[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Event filter to fire gamepad sensor events from system sensor events
|
||||
*
|
||||
* We don't use SDL_GamepadEventWatcher() for this because we want to
|
||||
* deliver gamepad sensor events when system sensor events are disabled,
|
||||
* and we also need to avoid a potential deadlock where joystick event
|
||||
* delivery locks the joysticks and then the event queue, but sensor
|
||||
* event delivery would lock the event queue and then from within the
|
||||
* event watcher function lock the joysticks.
|
||||
*/
|
||||
void SDL_GamepadSensorWatcher(Uint64 timestamp, SDL_SensorID sensor, Uint64 sensor_timestamp, float *data, int num_values)
|
||||
{
|
||||
SDL_Gamepad *gamepad;
|
||||
|
||||
SDL_LockJoysticks();
|
||||
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
|
||||
if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == sensor) {
|
||||
float gamepad_data[3];
|
||||
AdjustSensorOrientation(gamepad->joystick, data, gamepad_data);
|
||||
SDL_SendJoystickSensor(timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, sensor_timestamp, gamepad_data, SDL_arraysize(gamepad_data));
|
||||
}
|
||||
if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == sensor) {
|
||||
float gamepad_data[3];
|
||||
AdjustSensorOrientation(gamepad->joystick, data, gamepad_data);
|
||||
SDL_SendJoystickSensor(timestamp, gamepad->joystick, SDL_SENSOR_GYRO, sensor_timestamp, gamepad_data, SDL_arraysize(gamepad_data));
|
||||
}
|
||||
}
|
||||
SDL_UnlockJoysticks();
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/*
|
||||
* Helper function to guess at a mapping based on the elements reported for this gamepad
|
||||
|
|
|
@ -42,4 +42,7 @@ extern SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid)
|
|||
/* Handle delayed guide button on a gamepad */
|
||||
extern void SDL_GamepadHandleDelayedGuideButton(SDL_Joystick *joystick);
|
||||
|
||||
/* Handle system sensor data */
|
||||
extern void SDL_GamepadSensorWatcher(Uint64 timestamp, SDL_SensorID sensor, Uint64 sensor_timestamp, float *data, int num_values);
|
||||
|
||||
#endif /* SDL_gamepad_c_h_ */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#ifndef SDL_EVENTS_DISABLED
|
||||
#include "../events/SDL_events_c.h"
|
||||
#endif
|
||||
#include "../joystick/SDL_gamepad_c.h"
|
||||
|
||||
static SDL_SensorDriver *SDL_sensor_drivers[] = {
|
||||
#ifdef SDL_SENSOR_ANDROID
|
||||
|
@ -501,6 +502,9 @@ int SDL_SendSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_tim
|
|||
posted = SDL_PushEvent(&event) == 1;
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
SDL_GamepadSensorWatcher(timestamp, sensor->instance_id, sensor_timestamp, data, num_values);
|
||||
|
||||
return posted;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue