joystick: linux: Avoid checking for gamepad mapping each frame The information whether a specific joystick can be used as a gamepad is not going to change every frame, so we can cache the result into a variable. This dramatically reduces the performance impact of SDL2 on small embedded devices, since the code path that is now avoided was quite heavy. Fixes #4229. Signed-off-by: Paul Cercueil <paul@crapouillou.net>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c
index 466cee6..2064168 100644
--- a/src/joystick/linux/SDL_sysjoystick.c
+++ b/src/joystick/linux/SDL_sysjoystick.c
@@ -113,6 +113,9 @@ typedef struct SDL_joylist_item
/* Steam Controller support */
SDL_bool m_bSteamController;
+
+ SDL_GamepadMapping *mapping;
+ SDL_bool has_gamepad_mapping;
} SDL_joylist_item;
static SDL_joylist_item *SDL_joylist = NULL;
@@ -376,6 +379,7 @@ MaybeRemoveDevice(const char *path)
SDL_PrivateJoystickRemoved(item->device_instance);
+ SDL_free(item->mapping);
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
@@ -1403,6 +1407,21 @@ static SDL_bool
LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
{
SDL_Joystick *joystick;
+ SDL_joylist_item *item = JoystickByDevIndex(device_index);
+
+ if (item->has_gamepad_mapping) {
+ SDL_memcpy(out, item->mapping, sizeof(*out));
+ return SDL_TRUE;
+ }
+
+ if (item->mapping)
+ return SDL_FALSE;
+
+ item->mapping = (SDL_GamepadMapping *) SDL_calloc(sizeof(*item->mapping), 1);
+ if (item->mapping == NULL) {
+ SDL_OutOfMemory();
+ return SDL_FALSE;
+ }
joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
if (joystick == NULL) {
@@ -1566,6 +1585,9 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
LINUX_JoystickClose(joystick);
SDL_free(joystick);
+ SDL_memcpy(item->mapping, out, sizeof(*out));
+ item->has_gamepad_mapping = SDL_TRUE;
+
return SDL_TRUE;
}