From 2678789bd8c83dac86ef58fa2cc4cab7d11a3e98 Mon Sep 17 00:00:00 2001 From: rz5 Date: Wed, 13 Nov 2019 00:11:05 +0000 Subject: [PATCH 1/2] Refactor RetroArch input polling settings * Refactored the way RetroArch sets the input state/poll callbacks, hopefully it's clearer now. * The unnamed enum of poll type behaviors in core.h was moved to retroarch.h and is now named rarch_poll_type. It represents polling behaviors implemented specifically by RetroArch. First element starts at 1 to match the data encoding of RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE. * Created rarch_set_input_cbs - sets different input state/poll callbacks based on a rarch_poll_type parameter. * Replaced the static variable core_poll_type_override in retroarch.c with a poll_type_lock flag inside global_t's menu struct; RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE will now call rarch_set_input_cbs and set poll_type_lock, which blocks the user from changing behaviors from the menu. * To follow the RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE spec, we now set poll_type_lock and call rarch_set_input_cbs after calling unload_game. * core_set/unset_netplay_callbacks will now set/unset poll_type_lock, preventing the poll type from being changed by the user; * The MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR action will now call rarch_set_input_cbs if poll_type_lock isn't set, which means poll type is changed on-the-fly. --- config.def.h | 4 +- core.h | 14 ---- menu/menu_setting.c | 22 ++++-- retroarch.c | 162 ++++++++++++++++++++++---------------------- retroarch.h | 27 +++++++- 5 files changed, 127 insertions(+), 102 deletions(-) diff --git a/config.def.h b/config.def.h index a8f4049b64..bf7423c5a3 100644 --- a/config.def.h +++ b/config.def.h @@ -984,7 +984,9 @@ static const bool input_descriptor_hide_unbound = false; static const unsigned input_max_users = 5; -static const unsigned input_poll_type_behavior = 2; +/* Refer to retroarch.h, enum rarch_poll_type */ +/* Default behavior is "Late" */ +static const unsigned default_input_poll_type_behavior = 3; static const unsigned input_bind_timeout = 5; diff --git a/core.h b/core.h index 29fc95767d..456b1f48a9 100644 --- a/core.h +++ b/core.h @@ -28,20 +28,6 @@ RETRO_BEGIN_DECLS -enum -{ - /* Polling is performed before - * call to retro_run. */ - POLL_TYPE_EARLY = 0, - - /* Polling is performed when requested. */ - POLL_TYPE_NORMAL, - - /* Polling is performed on first call to - * retro_input_state per frame. */ - POLL_TYPE_LATE -}; - typedef struct rarch_memory_descriptor { struct retro_memory_descriptor core; diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 2af5c1d05a..4be0a60379 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -5475,17 +5475,17 @@ static void setting_get_string_representation_poll_type_behavior( switch (*setting->value.target.unsigned_integer) { - case 0: + case RARCH_POLL_TYPE_EARLY: strlcpy(s, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_EARLY), len); break; - case 1: + case RARCH_POLL_TYPE_NORMAL: strlcpy(s, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_NORMAL), len); break; - case 2: + case RARCH_POLL_TYPE_LATE: strlcpy(s, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_LATE), len); @@ -6261,8 +6261,20 @@ void general_write_handler(rarch_setting_t *setting) } break; case MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR: + { + global_t *global = global_get_ptr(); + + /* Core keeps track of the user-set poll type */ core_set_poll_type(*setting->value.target.integer); + + /* Frontend will change poll types if poll type isn't locked + * by e.g. Netplay or RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE */ + if (global && !(global->poll_type_lock)) + rarch_set_input_cbs(*setting->value.target.integer); + + /* TODO - OSD message when this fails because of the lock? */ break; + } case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER: { video_viewport_t vp; @@ -10584,7 +10596,7 @@ static bool setting_append_list( &settings->uints.input_poll_type_behavior, MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR, - input_poll_type_behavior, + default_input_poll_type_behavior, &group_info, &subgroup_info, parent_group, @@ -10594,7 +10606,7 @@ static bool setting_append_list( (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; (*list)[list_info->index - 1].get_string_representation = &setting_get_string_representation_poll_type_behavior; - menu_settings_list_current_add_range(list, list_info, 0, 2, 1, true, true); + menu_settings_list_current_add_range(list, list_info, RARCH_POLL_TYPE_MIN, RARCH_POLL_TYPE_MAX, 1, true, true); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED); #ifdef GEKKO diff --git a/retroarch.c b/retroarch.c index bc60b25215..ab3c009132 100644 --- a/retroarch.c +++ b/retroarch.c @@ -836,16 +836,6 @@ static settings_t *configuration_settings = NULL; static enum rarch_core_type current_core_type = CORE_TYPE_PLAIN; static enum rarch_core_type explicit_current_core_type = CORE_TYPE_PLAIN; -/* - * Override poll type behavior, is set by the core. - * - * 0 - Don't Care - * 1 - Early - * 2 - Normal - * 3 - Late - */ -static unsigned core_poll_type_override = 0; - static bool has_set_username = false; #ifdef HAVE_THREAD_STORAGE @@ -8674,28 +8664,33 @@ static bool rarch_environment_cb(unsigned cmd, void *data) * * Should all be properly addressed in version 2. * */ - case RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE: + { + const unsigned *poll_type_data = (const unsigned*)data; + + /* If the override is not "Don't Care", apply new behavior and lock it */ + if (poll_type_data && *poll_type_data > 0) { - const unsigned *poll_type_data = (const unsigned*)data; - - if (poll_type_data) - core_poll_type_override = *poll_type_data; + global_t *global = &g_extern; + rarch_set_input_cbs(*poll_type_data); + global->poll_type_lock = true; } - break; + break; + } + case RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB: *(retro_environment_t *)data = rarch_clear_all_thread_waits; break; case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND: - { - bool state = *(const bool*)data; - RARCH_LOG("[Environ]: SET_SAVE_STATE_IN_BACKGROUND: %s.\n", state ? "yes" : "no"); + { + bool state = *(const bool*)data; + RARCH_LOG("[Environ]: SET_SAVE_STATE_IN_BACKGROUND: %s.\n", state ? "yes" : "no"); - set_save_state_in_background(state); + set_save_state_in_background(state); - } + } break; @@ -9153,7 +9148,6 @@ static void secondary_core_destroy(void) /* unload game from core */ if (secondary_core.retro_unload_game) secondary_core.retro_unload_game(); - core_poll_type_override = 0; /* deinit */ if (secondary_core.retro_deinit) @@ -12526,6 +12520,19 @@ static int16_t input_state(unsigned port, unsigned device, return result; } +/* Polls hardware on the first input state request per frame */ +static int16_t rarch_input_state_with_late_poll(unsigned port, unsigned device, + unsigned idx, unsigned id) +{ + if (!current_core.input_polled) + { + input_driver_poll(); + current_core.input_polled = true; + } + + return input_state(port, device, idx, id); +} + static INLINE bool input_keys_pressed_other_sources(unsigned i, input_bits_t* p_new_state) { @@ -19817,14 +19824,10 @@ static void video_driver_frame(const void *data, unsigned width, if (!video_driver_active) return; - if (data) - frame_cache_data = data; - frame_cache_width = width; - frame_cache_height = height; - frame_cache_pitch = pitch; - + video_driver_cached_frame_set(data, width, height, pitch); + if ( - video_driver_scaler_ptr + video_driver_scaler_ptr && data && (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555) && (data != RETRO_HW_FRAME_BUFFER_VALID) @@ -22058,12 +22061,16 @@ static void runahead_destroy(void) static void unload_hook(void) { + global_t *global = &g_extern; runahead_remove_hooks(); runahead_destroy(); secondary_core_destroy(); if (current_core.retro_unload_game) current_core.retro_unload_game(); - core_poll_type_override = 0; + + /* RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE requirement */ + global->poll_type_lock = false; + rarch_set_input_cbs(current_core.poll_type); } static void runahead_deinit_hook(void) @@ -27069,41 +27076,6 @@ static void retro_input_poll_null(void) { } -static int16_t core_input_state_poll(unsigned port, - unsigned device, unsigned idx, unsigned id) -{ - return input_state(port, device, idx, id); -} - -static int16_t core_input_state_poll_late(unsigned port, - unsigned device, unsigned idx, unsigned id) -{ - if (!current_core.input_polled) - input_driver_poll(); - - current_core.input_polled = true; - return input_state(port, device, idx, id); -} - -static retro_input_state_t core_input_state_poll_return_cb(void) -{ - unsigned new_poll_type = (core_poll_type_override > 0) - ? (core_poll_type_override - 1) - : current_core.poll_type; - if (new_poll_type == POLL_TYPE_LATE) - return core_input_state_poll_late; - return core_input_state_poll; -} - -static void core_input_state_poll_maybe(void) -{ - unsigned new_poll_type = (core_poll_type_override > 0) - ? (core_poll_type_override - 1) - : current_core.poll_type; - if (new_poll_type == POLL_TYPE_NORMAL) - input_driver_poll(); -} - /** * core_init_libretro_cbs: * @data : pointer to retro_callbacks object @@ -27113,13 +27085,10 @@ static void core_input_state_poll_maybe(void) **/ static bool core_init_libretro_cbs(struct retro_callbacks *cbs) { - retro_input_state_t state_cb = core_input_state_poll_return_cb(); - current_core.retro_set_video_refresh(video_driver_frame); current_core.retro_set_audio_sample(audio_driver_sample); current_core.retro_set_audio_sample_batch(audio_driver_sample_batch); - current_core.retro_set_input_state(state_cb); - current_core.retro_set_input_poll(core_input_state_poll_maybe); + rarch_set_input_cbs(current_core.poll_type); core_set_default_callbacks(cbs); @@ -27133,6 +27102,31 @@ static bool core_init_libretro_cbs(struct retro_callbacks *cbs) return true; } +/** + * Sets input state/poll callbacks on + * current_core with different behaviors based on @poll_type . + */ +void rarch_set_input_cbs(enum rarch_poll_type poll_type) +{ + switch (poll_type) + { + case RARCH_POLL_TYPE_NORMAL: + current_core.retro_set_input_poll(input_driver_poll); + current_core.retro_set_input_state(input_state); + break; + case RARCH_POLL_TYPE_EARLY: + current_core.retro_set_input_poll(retro_input_poll_null); + current_core.retro_set_input_state(input_state); + break; + default: + /* Fall through. Default behavior is Late. */ + case RARCH_POLL_TYPE_LATE: + current_core.retro_set_input_poll(retro_input_poll_null); + current_core.retro_set_input_state(rarch_input_state_with_late_poll); + break; + } +} + /** * core_set_default_callbacks: * @data : pointer to retro_callbacks object @@ -27141,12 +27135,10 @@ static bool core_init_libretro_cbs(struct retro_callbacks *cbs) **/ bool core_set_default_callbacks(struct retro_callbacks *cbs) { - retro_input_state_t state_cb = core_input_state_poll_return_cb(); - cbs->frame_cb = video_driver_frame; cbs->sample_cb = audio_driver_sample; cbs->sample_batch_cb = audio_driver_sample_batch; - cbs->state_cb = state_cb; + cbs->state_cb = input_state; cbs->poll_cb = input_driver_poll; return true; @@ -27182,8 +27174,13 @@ bool core_set_rewind_callbacks(void) **/ bool core_set_netplay_callbacks(void) { + global_t *global = &g_extern; + /* Force normal poll type for netplay. */ - current_core.poll_type = POLL_TYPE_NORMAL; + rarch_set_input_cbs(RARCH_POLL_TYPE_NORMAL); + + /* Block poll type from being changed by the user via the menu */ + global->poll_type_lock = true; /* And use netplay's interceding callbacks */ current_core.retro_set_video_refresh(video_frame_net); @@ -27202,6 +27199,7 @@ bool core_set_netplay_callbacks(void) */ bool core_unset_netplay_callbacks(void) { + global_t *global = &g_extern; struct retro_callbacks cbs; if (!core_set_default_callbacks(&cbs)) return false; @@ -27209,7 +27207,8 @@ bool core_unset_netplay_callbacks(void) current_core.retro_set_video_refresh(cbs.frame_cb); current_core.retro_set_audio_sample(cbs.sample_cb); current_core.retro_set_audio_sample_batch(cbs.sample_batch_cb); - current_core.retro_set_input_state(cbs.state_cb); + global->poll_type_lock = false; + rarch_set_input_cbs(current_core.poll_type); return true; } @@ -27339,8 +27338,14 @@ static bool core_unload_game(void) if (current_core.game_loaded) { + global_t *global = &g_extern; current_core.retro_unload_game(); - core_poll_type_override = 0; + + /* RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE requirement */ + /* Unlock changing poll types and change it to the user-set poll type */ + global->poll_type_lock = false; + rarch_set_input_cbs(current_core.poll_type); + current_core.game_loaded = false; } @@ -27351,11 +27356,8 @@ static bool core_unload_game(void) bool core_run(void) { - unsigned new_poll_type = (core_poll_type_override != 0) - ? (core_poll_type_override - 1) - : current_core.poll_type; - bool early_polling = new_poll_type == POLL_TYPE_EARLY; - bool late_polling = new_poll_type == POLL_TYPE_LATE; + bool early_polling = current_core.poll_type == RARCH_POLL_TYPE_EARLY; + bool late_polling = current_core.poll_type == RARCH_POLL_TYPE_LATE; #ifdef HAVE_NETWORKING bool netplay_preframe = netplay_driver_ctl( RARCH_NETPLAY_CTL_PRE_FRAME, NULL); diff --git a/retroarch.h b/retroarch.h index 6e8a1c7da7..7cca87762d 100644 --- a/retroarch.h +++ b/retroarch.h @@ -67,7 +67,7 @@ RETRO_BEGIN_DECLS #define RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE (4 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) /* unsigned * -- * Tells the frontend to override the poll type behavior. - * Allows the frontend to influence the polling behavior of the + * Allows the core to influence the polling behavior of the * frontend. * * Will be unset when retro_unload_game is called. @@ -208,6 +208,26 @@ enum rarch_override_setting RARCH_OVERRIDE_SETTING_LAST }; +/* RetroArch input polling behavior */ +enum rarch_poll_type +{ + RARCH_POLL_TYPE_MIN = 1, + + /* Polling is performed before retro_run. + * The core's polling requests will be ignored. */ + RARCH_POLL_TYPE_EARLY = RARCH_POLL_TYPE_MIN, + + /* Polling is performed when requested. */ + RARCH_POLL_TYPE_NORMAL, + + /* Polling is performed on first call to retro_input_state per frame + * or after retro_run if it retro_input_state wasn't called. + * The core's polling requests will be ignored. */ + RARCH_POLL_TYPE_LATE, + + RARCH_POLL_TYPE_MAX = RARCH_POLL_TYPE_LATE +}; + enum runloop_action { RUNLOOP_ACTION_NONE = 0, @@ -299,9 +319,10 @@ typedef struct global retro_time_t noop_start_time ; retro_time_t action_start_time ; retro_time_t action_press_time ; - enum menu_action prev_action ; + enum menu_action prev_action ; } menu; #endif + bool poll_type_lock; /* RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE and Netplay */ } global_t; bool rarch_ctl(enum rarch_ctl_state state, void *data); @@ -399,6 +420,8 @@ void rarch_favorites_init(void); void rarch_favorites_deinit(void); +void rarch_set_input_cbs(enum rarch_poll_type type); + /* Audio */ #ifdef HAVE_AUDIOMIXER From 82898ea194df9e864f39a377c2cad9bc8560f2f5 Mon Sep 17 00:00:00 2001 From: rz5 Date: Fri, 15 Nov 2019 00:47:46 +0000 Subject: [PATCH 2/2] Cast arg to rarch_set_in_put from what it is to enum rarch_poll_type. Might fix building under clang 6.0 --- menu/menu_setting.c | 2 +- retroarch.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 4be0a60379..7edf54ca5e 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -6270,7 +6270,7 @@ void general_write_handler(rarch_setting_t *setting) /* Frontend will change poll types if poll type isn't locked * by e.g. Netplay or RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE */ if (global && !(global->poll_type_lock)) - rarch_set_input_cbs(*setting->value.target.integer); + rarch_set_input_cbs((enum rarch_poll_type)*setting->value.target.integer); /* TODO - OSD message when this fails because of the lock? */ break; diff --git a/retroarch.c b/retroarch.c index ab3c009132..182d646c8c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -8672,7 +8672,7 @@ static bool rarch_environment_cb(unsigned cmd, void *data) if (poll_type_data && *poll_type_data > 0) { global_t *global = &g_extern; - rarch_set_input_cbs(*poll_type_data); + rarch_set_input_cbs((enum rarch_poll_type)(*poll_type_data)); global->poll_type_lock = true; } @@ -22070,7 +22070,7 @@ static void unload_hook(void) /* RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE requirement */ global->poll_type_lock = false; - rarch_set_input_cbs(current_core.poll_type); + rarch_set_input_cbs((enum rarch_poll_type)current_core.poll_type); } static void runahead_deinit_hook(void) @@ -27088,7 +27088,7 @@ static bool core_init_libretro_cbs(struct retro_callbacks *cbs) current_core.retro_set_video_refresh(video_driver_frame); current_core.retro_set_audio_sample(audio_driver_sample); current_core.retro_set_audio_sample_batch(audio_driver_sample_batch); - rarch_set_input_cbs(current_core.poll_type); + rarch_set_input_cbs((enum rarch_poll_type)current_core.poll_type); core_set_default_callbacks(cbs); @@ -27208,7 +27208,7 @@ bool core_unset_netplay_callbacks(void) current_core.retro_set_audio_sample(cbs.sample_cb); current_core.retro_set_audio_sample_batch(cbs.sample_batch_cb); global->poll_type_lock = false; - rarch_set_input_cbs(current_core.poll_type); + rarch_set_input_cbs((enum rarch_poll_type)current_core.poll_type); return true; } @@ -27344,7 +27344,7 @@ static bool core_unload_game(void) /* RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE requirement */ /* Unlock changing poll types and change it to the user-set poll type */ global->poll_type_lock = false; - rarch_set_input_cbs(current_core.poll_type); + rarch_set_input_cbs((enum rarch_poll_type)current_core.poll_type); current_core.game_loaded = false; }