1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-05 09:48:42 +00:00

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.
This commit is contained in:
rz5 2019-11-13 00:11:05 +00:00
parent baaf27c268
commit 2678789bd8
5 changed files with 127 additions and 102 deletions

View File

@ -984,7 +984,9 @@ static const bool input_descriptor_hide_unbound = false;
static const unsigned input_max_users = 5; 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; static const unsigned input_bind_timeout = 5;

14
core.h
View File

@ -28,20 +28,6 @@
RETRO_BEGIN_DECLS 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 typedef struct rarch_memory_descriptor
{ {
struct retro_memory_descriptor core; struct retro_memory_descriptor core;

View File

@ -5475,17 +5475,17 @@ static void setting_get_string_representation_poll_type_behavior(
switch (*setting->value.target.unsigned_integer) switch (*setting->value.target.unsigned_integer)
{ {
case 0: case RARCH_POLL_TYPE_EARLY:
strlcpy(s, strlcpy(s,
msg_hash_to_str( msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_EARLY), len); MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_EARLY), len);
break; break;
case 1: case RARCH_POLL_TYPE_NORMAL:
strlcpy(s, strlcpy(s,
msg_hash_to_str( msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_NORMAL), len); MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_NORMAL), len);
break; break;
case 2: case RARCH_POLL_TYPE_LATE:
strlcpy(s, strlcpy(s,
msg_hash_to_str( msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_LATE), len); MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_LATE), len);
@ -6261,8 +6261,20 @@ void general_write_handler(rarch_setting_t *setting)
} }
break; break;
case MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR: 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); 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; break;
}
case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER: case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER:
{ {
video_viewport_t vp; video_viewport_t vp;
@ -10584,7 +10596,7 @@ static bool setting_append_list(
&settings->uints.input_poll_type_behavior, &settings->uints.input_poll_type_behavior,
MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR,
MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR, MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR,
input_poll_type_behavior, default_input_poll_type_behavior,
&group_info, &group_info,
&subgroup_info, &subgroup_info,
parent_group, 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].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation = (*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_poll_type_behavior; &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); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED);
#ifdef GEKKO #ifdef GEKKO

View File

@ -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 current_core_type = CORE_TYPE_PLAIN;
static enum rarch_core_type explicit_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; static bool has_set_username = false;
#ifdef HAVE_THREAD_STORAGE #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. * Should all be properly addressed in version 2.
* */ * */
case RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE: 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; global_t *global = &g_extern;
rarch_set_input_cbs(*poll_type_data);
if (poll_type_data) global->poll_type_lock = true;
core_poll_type_override = *poll_type_data;
} }
break;
break;
}
case RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB: case RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB:
*(retro_environment_t *)data = rarch_clear_all_thread_waits; *(retro_environment_t *)data = rarch_clear_all_thread_waits;
break; break;
case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND: case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND:
{ {
bool state = *(const bool*)data; bool state = *(const bool*)data;
RARCH_LOG("[Environ]: SET_SAVE_STATE_IN_BACKGROUND: %s.\n", state ? "yes" : "no"); 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; break;
@ -9153,7 +9148,6 @@ static void secondary_core_destroy(void)
/* unload game from core */ /* unload game from core */
if (secondary_core.retro_unload_game) if (secondary_core.retro_unload_game)
secondary_core.retro_unload_game(); secondary_core.retro_unload_game();
core_poll_type_override = 0;
/* deinit */ /* deinit */
if (secondary_core.retro_deinit) if (secondary_core.retro_deinit)
@ -12526,6 +12520,19 @@ static int16_t input_state(unsigned port, unsigned device,
return result; 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, static INLINE bool input_keys_pressed_other_sources(unsigned i,
input_bits_t* p_new_state) input_bits_t* p_new_state)
{ {
@ -19817,14 +19824,10 @@ static void video_driver_frame(const void *data, unsigned width,
if (!video_driver_active) if (!video_driver_active)
return; return;
if (data) video_driver_cached_frame_set(data, width, height, pitch);
frame_cache_data = data;
frame_cache_width = width;
frame_cache_height = height;
frame_cache_pitch = pitch;
if ( if (
video_driver_scaler_ptr video_driver_scaler_ptr
&& data && data
&& (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555) && (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555)
&& (data != RETRO_HW_FRAME_BUFFER_VALID) && (data != RETRO_HW_FRAME_BUFFER_VALID)
@ -22058,12 +22061,16 @@ static void runahead_destroy(void)
static void unload_hook(void) static void unload_hook(void)
{ {
global_t *global = &g_extern;
runahead_remove_hooks(); runahead_remove_hooks();
runahead_destroy(); runahead_destroy();
secondary_core_destroy(); secondary_core_destroy();
if (current_core.retro_unload_game) if (current_core.retro_unload_game)
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) 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: * core_init_libretro_cbs:
* @data : pointer to retro_callbacks object * @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) 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_video_refresh(video_driver_frame);
current_core.retro_set_audio_sample(audio_driver_sample); current_core.retro_set_audio_sample(audio_driver_sample);
current_core.retro_set_audio_sample_batch(audio_driver_sample_batch); current_core.retro_set_audio_sample_batch(audio_driver_sample_batch);
current_core.retro_set_input_state(state_cb); rarch_set_input_cbs(current_core.poll_type);
current_core.retro_set_input_poll(core_input_state_poll_maybe);
core_set_default_callbacks(cbs); core_set_default_callbacks(cbs);
@ -27133,6 +27102,31 @@ static bool core_init_libretro_cbs(struct retro_callbacks *cbs)
return true; 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: * core_set_default_callbacks:
* @data : pointer to retro_callbacks object * @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) 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->frame_cb = video_driver_frame;
cbs->sample_cb = audio_driver_sample; cbs->sample_cb = audio_driver_sample;
cbs->sample_batch_cb = audio_driver_sample_batch; cbs->sample_batch_cb = audio_driver_sample_batch;
cbs->state_cb = state_cb; cbs->state_cb = input_state;
cbs->poll_cb = input_driver_poll; cbs->poll_cb = input_driver_poll;
return true; return true;
@ -27182,8 +27174,13 @@ bool core_set_rewind_callbacks(void)
**/ **/
bool core_set_netplay_callbacks(void) bool core_set_netplay_callbacks(void)
{ {
global_t *global = &g_extern;
/* Force normal poll type for netplay. */ /* 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 */ /* And use netplay's interceding callbacks */
current_core.retro_set_video_refresh(video_frame_net); 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) bool core_unset_netplay_callbacks(void)
{ {
global_t *global = &g_extern;
struct retro_callbacks cbs; struct retro_callbacks cbs;
if (!core_set_default_callbacks(&cbs)) if (!core_set_default_callbacks(&cbs))
return false; 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_video_refresh(cbs.frame_cb);
current_core.retro_set_audio_sample(cbs.sample_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_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; return true;
} }
@ -27339,8 +27338,14 @@ static bool core_unload_game(void)
if (current_core.game_loaded) if (current_core.game_loaded)
{ {
global_t *global = &g_extern;
current_core.retro_unload_game(); 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; current_core.game_loaded = false;
} }
@ -27351,11 +27356,8 @@ static bool core_unload_game(void)
bool core_run(void) bool core_run(void)
{ {
unsigned new_poll_type = (core_poll_type_override != 0) bool early_polling = current_core.poll_type == RARCH_POLL_TYPE_EARLY;
? (core_poll_type_override - 1) bool late_polling = current_core.poll_type == RARCH_POLL_TYPE_LATE;
: current_core.poll_type;
bool early_polling = new_poll_type == POLL_TYPE_EARLY;
bool late_polling = new_poll_type == POLL_TYPE_LATE;
#ifdef HAVE_NETWORKING #ifdef HAVE_NETWORKING
bool netplay_preframe = netplay_driver_ctl( bool netplay_preframe = netplay_driver_ctl(
RARCH_NETPLAY_CTL_PRE_FRAME, NULL); RARCH_NETPLAY_CTL_PRE_FRAME, NULL);

View File

@ -67,7 +67,7 @@ RETRO_BEGIN_DECLS
#define RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE (4 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) #define RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE (4 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK)
/* unsigned * -- /* unsigned * --
* Tells the frontend to override the poll type behavior. * 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. * frontend.
* *
* Will be unset when retro_unload_game is called. * Will be unset when retro_unload_game is called.
@ -208,6 +208,26 @@ enum rarch_override_setting
RARCH_OVERRIDE_SETTING_LAST 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 enum runloop_action
{ {
RUNLOOP_ACTION_NONE = 0, RUNLOOP_ACTION_NONE = 0,
@ -299,9 +319,10 @@ typedef struct global
retro_time_t noop_start_time ; retro_time_t noop_start_time ;
retro_time_t action_start_time ; retro_time_t action_start_time ;
retro_time_t action_press_time ; retro_time_t action_press_time ;
enum menu_action prev_action ; enum menu_action prev_action ;
} menu; } menu;
#endif #endif
bool poll_type_lock; /* RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE and Netplay */
} global_t; } global_t;
bool rarch_ctl(enum rarch_ctl_state state, void *data); 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_favorites_deinit(void);
void rarch_set_input_cbs(enum rarch_poll_type type);
/* Audio */ /* Audio */
#ifdef HAVE_AUDIOMIXER #ifdef HAVE_AUDIOMIXER