Skip to content

Commit

Permalink
gamepad: initialize in a thread
Browse files Browse the repository at this point in the history
Speeds up game startup, at least on Linux
  • Loading branch information
Akaricchi committed Apr 27, 2024
1 parent 17815c6 commit 51bcae7
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef enum {
TE_GAMEPAD_BUTTON_UP,
TE_GAMEPAD_AXIS,
TE_GAMEPAD_AXIS_DIGITAL,
TE_GAMEPAD_SDL_INITIALIZED,

TE_VIDEO_MODE_CHANGED,

Expand Down
66 changes: 55 additions & 11 deletions src/gamepad.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "events.h"
#include "global.h"
#include "hirestime.h"
#include "taskmanager.h"

typedef struct GamepadAxisState {
int16_t raw;
Expand All @@ -34,7 +35,9 @@ static struct {
GamepadAxisState *axes;
GamepadButtonState *buttons;
DYNAMIC_ARRAY(GamepadDevice) devices;
Task *init_task;
int active_dev_num;
bool initializing;
bool initialized;
bool update_needed;
} gamepad;
Expand Down Expand Up @@ -281,23 +284,26 @@ static inline void set_events_state(int state) {
SDL_GameControllerEventState(state);
}

void gamepad_init(void) {
if(gamepad.initialized) {
return;
static void *gamepad_init_task(void *arg) {
if(SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
log_sdl_error(LOG_ERROR, "SDL_InitSubSystem");
}

set_events_state(SDL_IGNORE);
events_emit(TE_GAMEPAD_SDL_INITIALIZED, 0, NULL, NULL);
return NULL;
}

if(!config_get_int(CONFIG_GAMEPAD_ENABLED)) {
return;
}
static bool gamepad_post_init_event(SDL_Event *evt, void *arg) {
assert(evt->type == MAKE_TAISEI_EVENT(TE_GAMEPAD_SDL_INITIALIZED));
bool success = SDL_WasInit(SDL_INIT_GAMECONTROLLER);

if(SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
log_sdl_error(LOG_ERROR, "SDL_InitSubSystem");
return;
events_unregister_handler(gamepad_post_init_event);

if(!success) {
log_debug("Gamepad init failed");
goto end;
}

gamepad.initialized = true;
gamepad.update_needed = true;
gamepad.axes = ALLOC_ARRAY(GAMEPAD_AXIS_MAX, typeof(*gamepad.axes));
gamepad.buttons = ALLOC_ARRAY(GAMEPAD_BUTTON_MAX + GAMEPAD_EMULATED_BUTTON_MAX, typeof(*gamepad.buttons));
Expand All @@ -310,13 +316,51 @@ void gamepad_init(void) {
});

set_events_state(SDL_ENABLE);
gamepad.initialized = true;

end:
task_finish(gamepad.init_task, NULL);
gamepad.init_task = NULL;
gamepad.initializing = false;
return true;
}

void gamepad_init(void) {
if(gamepad.initialized || gamepad.initializing) {
return;
}

set_events_state(SDL_IGNORE);

if(!config_get_int(CONFIG_GAMEPAD_ENABLED)) {
return;
}

gamepad.initializing = true;

events_register_handler(&(EventHandler){
.proc = gamepad_post_init_event,
.priority = EPRIO_SYSTEM,
.event_type = MAKE_TAISEI_EVENT(TE_GAMEPAD_SDL_INITIALIZED),
});

gamepad.init_task = taskmgr_global_submit((TaskParams) {
.callback = gamepad_init_task,
.prio = -10,
.topmost = true,
});
}

void gamepad_shutdown(void) {
if(!gamepad.initialized) {
return;
}

if(gamepad.init_task) {
task_finish(gamepad.init_task, NULL);
gamepad.init_task = NULL;
}

log_info("Disabled the gamepad subsystem");

mem_free(gamepad.axes);
Expand Down

0 comments on commit 51bcae7

Please sign in to comment.