runloop: put cheats, presence, camera and BSV behind frame_work bits

The post-core_run product block called into four translation units
every frame to find out nothing needed doing: cheat_manager_apply_
retro_cheats() loads a cold global to see there is no cheat list,
presence_update() calls discord_update() and steam_update_presence()
which each compare a status word and return, the camera poll reads
settings_t for camera_allow before the caps check, and
bsv_movie_next_frame() pulled two settings through config_get_ptr()
before checking whether a movie handle exists at all.

Give each an up/down owner and a bit on runloop_state_t::frame_work,
raised and dropped by the product itself through
runloop_frame_work_set():

  RUNLOOP_WORK_CHEATS   - cheat_manager_new/realloc raise it when a
                          list is allocated, cheat_manager_free drops it
  RUNLOOP_WORK_PRESENCE - raised with Discord init and with Steam
                          (mist) init; dropped with whichever of the
                          two is the last compiled-in sink
  RUNLOOP_WORK_CAMERA   - driver_camera_start raises it when the core's
                          start succeeds, driver_camera_stop and the
                          driver teardown drop it. The remaining
                          camera_allow/caps/driver checks stay behind
                          the bit; a camera the core registered but
                          never started is no longer polled.

BSV needs no bit: the movie handles live on input_st, which the frame
already has in cache, so the iterate tests the pointers directly and
bsv_movie_next_frame() checks its handle before touching settings.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-09-29 20:11:58 +02:00
1 parent 34d87d5574
commit e39e641802
7 files changed
+60 -13

No files matched your search

+6 -1
View File
@@ -110,7 +110,11 @@ bool driver_camera_start(void)
settings_t *settings = config_get_ptr();
bool camera_allow = settings->bools.camera_allow;
if (camera_allow)
return camera_st->driver->start(camera_st->data);
{
bool ok = camera_st->driver->start(camera_st->data);
runloop_frame_work_set(RUNLOOP_WORK_CAMERA, ok);
return ok;
}
runloop_msg_queue_push(
"Camera is explicitly disabled.\n",
@@ -128,6 +132,7 @@ void driver_camera_stop(void)
&& camera_st->driver->stop
&& camera_st->data)
camera_st->driver->stop(camera_st->data);
runloop_frame_work_set(RUNLOOP_WORK_CAMERA, false);
}
bool camera_driver_find_driver(const char *prefix,
+5
View File
@@ -411,6 +411,7 @@ static void cheat_manager_free(void)
cheat_st->num_memory_buffers = 0;
cheat_st->total_memory_size = 0;
cheat_st->memory_initialized = false;
runloop_frame_work_set(RUNLOOP_WORK_CHEATS, false);
}
static void cheat_manager_new(unsigned size)
@@ -431,8 +432,10 @@ static void cheat_manager_new(unsigned size)
cheat_st->buf_size = 0;
cheat_st->size = 0;
cheat_st->cheats = NULL;
runloop_frame_work_set(RUNLOOP_WORK_CHEATS, false);
return;
}
runloop_frame_work_set(RUNLOOP_WORK_CHEATS, true);
for (i = 0; i < cheat_st->size; i++)
{
@@ -674,8 +677,10 @@ bool cheat_manager_realloc(unsigned new_size, unsigned default_handler)
{
cheat_st->buf_size = cheat_st->size = 0;
cheat_st->cheats = NULL;
runloop_frame_work_set(RUNLOOP_WORK_CHEATS, false);
return false;
}
runloop_frame_work_set(RUNLOOP_WORK_CHEATS, true);
cheat_st->buf_size = new_size;
cheat_st->size = new_size;
+4 -2
View File
@@ -1015,8 +1015,8 @@ void bsv_movie_scan_from_start(bsv_movie_t *movie, int32_t len)
void bsv_movie_next_frame(input_driver_state_t *input_st)
{
unsigned checkpoint_interval = config_get_ptr()->uints.replay_checkpoint_interval;
unsigned checkpoint_deserialize= config_get_ptr()->bools.replay_checkpoint_deserialize;
unsigned checkpoint_interval;
unsigned checkpoint_deserialize;
/* If bsv_movie_state_next_handle is not NULL, deinit and set
bsv_movie_state_handle to bsv_movie_state_next_handle and clear
next_handle */
@@ -1024,6 +1024,8 @@ void bsv_movie_next_frame(input_driver_state_t *input_st)
if (!handle)
return;
checkpoint_interval = config_get_ptr()->uints.replay_checkpoint_interval;
checkpoint_deserialize = config_get_ptr()->bools.replay_checkpoint_deserialize;
#ifdef HAVE_REWIND
if (state_manager_frame_is_reversed())
{
+5 -1
View File
@@ -1989,6 +1989,7 @@ void driver_uninit(int flags, enum driver_lifetime_flags lifetime_flags)
}
camera_st->data = NULL;
runloop_frame_work_set(RUNLOOP_WORK_CAMERA, false);
}
#ifdef HAVE_BLUETOOTH
@@ -8998,7 +8999,7 @@ bool retroarch_main_init(int argc, char *argv[])
if (command_event(CMD_EVENT_DISCORD_INIT, NULL))
{
discord_st->inited = true;
runloop_st->frame_work |= RUNLOOP_WORK_DISCORD;
runloop_st->frame_work |= RUNLOOP_WORK_DISCORD | RUNLOOP_WORK_PRESENCE;
}
}
#endif
@@ -9695,6 +9696,9 @@ bool retroarch_main_quit(void)
}
discord_st->inited = false;
runloop_st->frame_work &= ~RUNLOOP_WORK_DISCORD;
#ifndef HAVE_MIST
runloop_st->frame_work &= ~RUNLOOP_WORK_PRESENCE;
#endif
}
#endif
+25 -8
View File
@@ -455,6 +455,14 @@ runloop_state_t *runloop_state_get_ptr(void)
return &runloop_state;
}
void runloop_frame_work_set(unsigned bit, bool on)
{
if (on)
runloop_state.frame_work |= bit;
else
runloop_state.frame_work &= ~bit;
}
bool runloop_is_content_closing(void)
{
return runloop_state.content_closing;
@@ -8362,7 +8370,8 @@ int runloop_iterate(void)
#endif
#ifdef HAVE_BSV_MOVIE
bsv_movie_dequeue_next(input_st);
if (input_st->bsv_movie_state_next_handle)
bsv_movie_dequeue_next(input_st);
#endif
#ifdef ANDROID
@@ -8614,7 +8623,8 @@ int runloop_iterate(void)
autosave_lock();
#endif
if ( settings->bools.camera_allow
if ( (runloop_st->frame_work & RUNLOOP_WORK_CAMERA)
&& settings->bools.camera_allow
&& camera_st->cb.caps
&& camera_st->driver
&& camera_st->driver->poll
@@ -8663,17 +8673,24 @@ int runloop_iterate(void)
rcheevos_test();
#endif
#ifdef HAVE_CHEATS
cheat_manager_apply_retro_cheats();
if (runloop_st->frame_work & RUNLOOP_WORK_CHEATS)
cheat_manager_apply_retro_cheats();
#endif
#ifdef HAVE_PRESENCE
presence_update(PRESENCE_GAME);
if (runloop_st->frame_work & RUNLOOP_WORK_PRESENCE)
presence_update(PRESENCE_GAME);
#endif
#ifdef HAVE_BSV_MOVIE
bsv_movie_next_frame(input_st);
if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_END)
/* The movie handle lives on input_st, which this frame already
* has in cache; no bit needed. */
if (input_st->bsv_movie_state_handle)
{
movie_stop(input_st);
command_event(CMD_EVENT_PAUSE, NULL);
bsv_movie_next_frame(input_st);
if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_END)
{
movie_stop(input_st);
command_event(CMD_EVENT_PAUSE, NULL);
}
}
#endif
+7 -1
View File
@@ -748,9 +748,15 @@ typedef struct runloop runloop_state_t;
/* runloop_state_t::frame_work bits */
enum runloop_frame_work
{
RUNLOOP_WORK_DISCORD = (1 << 0) /* Discord RPC is up: pump it */
RUNLOOP_WORK_DISCORD = (1 << 0), /* Discord RPC is up: pump it */
RUNLOOP_WORK_PRESENCE = (1 << 1), /* a rich-presence sink is up */
RUNLOOP_WORK_CHEATS = (1 << 2), /* a cheat list is loaded */
RUNLOOP_WORK_CAMERA = (1 << 3) /* the core started the camera */
};
/* Raise or drop one frame_work bit from the product that owns it. */
void runloop_frame_work_set(unsigned bit, bool on);
/* Runs deferred off-main message pushes; the main thread, once per
* iterate. */
void runloop_msg_queue_drain_deferred(void);
+8
View File
@@ -28,7 +28,10 @@ void steam_init(void)
MistResult result = mist_subprocess_init();
if (MIST_IS_SUCCESS(result))
{
mist_initialized = true;
runloop_frame_work_set(RUNLOOP_WORK_PRESENCE, true);
}
else
RARCH_ERR("[Steam] Failed to initialize mist subprocess (%d-%d).\n", MIST_UNPACK_RESULT(result));
}
@@ -520,7 +523,12 @@ void steam_deinit(void)
steam_core_dlc_list_free(mist_dlc_list);
if (MIST_IS_SUCCESS(result))
{
mist_initialized = false;
#ifndef HAVE_DISCORD
runloop_frame_work_set(RUNLOOP_WORK_PRESENCE, false);
#endif
}
else
RARCH_ERR("[Steam] Failed to deinitialize mist subprocess (%d-%d).\n", MIST_UNPACK_RESULT(result));
}