Both the 'pause' state and the 'menu' state return 1 - so that
we can signal to the Apple upper-layer function that we want to run CFRunLoopWakeUp
This commit is contained in:
parent
291f4579a2
commit
458eff5f4d
|
@ -56,7 +56,9 @@
|
||||||
|
|
||||||
int main_entry_decide(signature(), args_type() args)
|
int main_entry_decide(signature(), args_type() args)
|
||||||
{
|
{
|
||||||
if (rarch_main_iterate() == -1)
|
int ret = rarch_main_iterate();
|
||||||
|
|
||||||
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (g_extern.core_shutdown_initiated
|
if (g_extern.core_shutdown_initiated
|
||||||
&& g_settings.load_dummy_on_core_shutdown)
|
&& g_settings.load_dummy_on_core_shutdown)
|
||||||
|
@ -66,13 +68,12 @@ int main_entry_decide(signature(), args_type() args)
|
||||||
g_extern.core_shutdown_initiated = false;
|
g_extern.core_shutdown_initiated = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (driver.frontend_ctx && driver.frontend_ctx->process_events)
|
if (driver.frontend_ctx && driver.frontend_ctx->process_events)
|
||||||
driver.frontend_ctx->process_events(args);
|
driver.frontend_ctx->process_events(args);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_exit(args_type() args)
|
void main_exit(args_type() args)
|
||||||
|
@ -241,7 +242,7 @@ returntype main_entry(signature())
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_MAIN_LOOP)
|
#if defined(HAVE_MAIN_LOOP)
|
||||||
while (!main_entry_decide(signature_expand(), args));
|
while (main_entry_decide(signature_expand(), args) != -1);
|
||||||
|
|
||||||
main_exit(args);
|
main_exit(args);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,73 +28,74 @@ static CFRunLoopObserverRef iterate_observer;
|
||||||
|
|
||||||
static void do_iteration(void)
|
static void do_iteration(void)
|
||||||
{
|
{
|
||||||
if (main_entry_decide(0, NULL, NULL))
|
int ret = main_entry_decide(0, NULL, NULL);
|
||||||
|
|
||||||
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
main_exit(NULL);
|
main_exit(NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
CFRunLoopWakeUp(CFRunLoopGetMain());
|
||||||
|
|
||||||
/* TODO/FIXME
|
/* TODO/FIXME
|
||||||
I am almost positive that this is not necessary and is actually a
|
I am almost positive that this is not necessary and is actually a
|
||||||
bad thing.
|
bad thing.
|
||||||
|
|
||||||
1st. Why it is bad thing.
|
1st. Why it is bad thing.
|
||||||
|
|
||||||
This wakes up the main event loop immediately and the main loop
|
This wakes up the main event loop immediately and the main loop
|
||||||
has only one observer, which is this function. In other words,
|
has only one observer, which is this function. In other words,
|
||||||
this causes the function to be called immediately. I did an
|
this causes the function to be called immediately. I did an
|
||||||
experiment where I saved the time before calling this and then
|
experiment where I saved the time before calling this and then
|
||||||
reported the difference between it and the start of
|
reported the difference between it and the start of
|
||||||
do_iteration, and as expected it was about 0. As a result, when
|
do_iteration, and as expected it was about 0. As a result, when
|
||||||
we remove this, idle performance (i.e. displaying the RetroArch
|
we remove this, idle performance (i.e. displaying the RetroArch
|
||||||
menu) is 0% CPU as desired.
|
menu) is 0% CPU as desired.
|
||||||
|
|
||||||
2nd. Why it is not necessary.
|
2nd. Why it is not necessary.
|
||||||
|
|
||||||
The event loop will wake up itself when there is input to the
|
The event loop will wake up itself when there is input to the
|
||||||
process. This includes touch events, keyboard, bluetooth,
|
process. This includes touch events, keyboard, bluetooth,
|
||||||
etc. Thus, it will be woken up and without any intervention so
|
etc. Thus, it will be woken up and without any intervention so
|
||||||
that we can process that event.
|
that we can process that event.
|
||||||
|
|
||||||
Nota bene. Why this analysis might be wrong (and what to do about it).
|
Nota bene. Why this analysis might be wrong (and what to do about it).
|
||||||
|
|
||||||
If RA is not idle and is running a core, then I believe it is
|
If RA is not idle and is running a core, then I believe it is
|
||||||
designed to expect to be called in a busy loop like this because
|
designed to expect to be called in a busy loop like this because
|
||||||
it implements its own frame timer to ensure that the emulation
|
it implements its own frame timer to ensure that the emulation
|
||||||
simulation isn't too fast. In that case, this change would only
|
simulation isn't too fast. In that case, this change would only
|
||||||
allow emulation to run when there was input, which would make
|
allow emulation to run when there was input, which would make
|
||||||
all games turn-based. :)
|
all games turn-based. :)
|
||||||
|
|
||||||
There are two good ways to fix this and still have the desired
|
There are two good ways to fix this and still have the desired
|
||||||
0% CPU idle behavior.
|
0% CPU idle behavior.
|
||||||
|
|
||||||
Approach 1: Change main_entry_decide from returning a boolean
|
Approach 1: Change main_entry_decide from returning a boolean
|
||||||
(two-values) that are interpreted as CONTINUE and QUIT. Into
|
(two-values) that are interpreted as CONTINUE and QUIT. Into
|
||||||
returning a char-sized enum with three values that are
|
returning a char-sized enum with three values that are
|
||||||
interpreted as QUIT, WAIT, and AGAIN, such that QUIT calls
|
interpreted as QUIT, WAIT, and AGAIN, such that QUIT calls
|
||||||
main_exit, WAIT doesn't wake up the loop, and AGAIN does. It
|
main_exit, WAIT doesn't wake up the loop, and AGAIN does. It
|
||||||
would then return AGAIN when a core was active. An ugly way to
|
would then return AGAIN when a core was active. An ugly way to
|
||||||
get the same effect is to look have this code just look at
|
get the same effect is to look have this code just look at
|
||||||
g_extern.is_menu and use the WAIT behavior in that case.
|
g_extern.is_menu and use the WAIT behavior in that case.
|
||||||
|
|
||||||
Approach 2: Instead of signalling outside of RA whether a core
|
Approach 2: Instead of signalling outside of RA whether a core
|
||||||
is running, instead externalize the frame time that is inside
|
is running, instead externalize the frame time that is inside
|
||||||
retroarch. change main_entry_decide to return a value in
|
retroarch. change main_entry_decide to return a value in
|
||||||
[-1,MAX_INT] where -1 is interpreted as QUIT, [0,MAX_INT) is
|
[-1,MAX_INT] where -1 is interpreted as QUIT, [0,MAX_INT) is
|
||||||
interpreted as the amount of time to wait until continuing, and
|
interpreted as the amount of time to wait until continuing, and
|
||||||
MAX_INT is interpreted as WAIT. This could be more robust
|
MAX_INT is interpreted as WAIT. This could be more robust
|
||||||
because we'd be exposing the scheduling behavior of RA to iOS,
|
because we'd be exposing the scheduling behavior of RA to iOS,
|
||||||
which might be good in other platforms as well.
|
which might be good in other platforms as well.
|
||||||
|
|
||||||
Approach 1 is the simplest and essentially just pushes down
|
Approach 1 is the simplest and essentially just pushes down
|
||||||
these requirements to rarch_main_iterate. I have gone with the
|
these requirements to rarch_main_iterate. I have gone with the
|
||||||
"ugly way" first because it is the most expedient and
|
"ugly way" first because it is the most expedient and
|
||||||
safe. Other eyeballs should decide if it isn't necessary.
|
safe. Other eyeballs should decide if it isn't necessary.
|
||||||
*/
|
*/
|
||||||
#if 0
|
|
||||||
if ( ! g_extern.is_menu )
|
|
||||||
CFRunLoopWakeUp(CFRunLoopGetMain());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void apple_start_iteration(void)
|
void apple_start_iteration(void)
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
|
|
||||||
static void emscripten_mainloop(void)
|
static void emscripten_mainloop(void)
|
||||||
{
|
{
|
||||||
if (main_entry_decide(0, NULL, NULL))
|
int ret = main_entry_decide(0, NULL, NULL)
|
||||||
|
|
||||||
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
main_exit(NULL);
|
main_exit(NULL);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
18
retroarch.c
18
retroarch.c
|
@ -3220,17 +3220,20 @@ static inline int time_to_exit(retro_input_t input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns:
|
/* Returns:
|
||||||
* 0 - Successful iteration.
|
* 0 - Successful iteration.
|
||||||
* -1 - Quit out of iteration loop.
|
* 1 - Forcibly wake up the loop.
|
||||||
|
* -1 - Quit out of iteration loop.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int rarch_main_iterate(void)
|
int rarch_main_iterate(void)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
retro_input_t trigger_input;
|
||||||
|
int ret = 0;
|
||||||
static retro_input_t last_input = 0;
|
static retro_input_t last_input = 0;
|
||||||
retro_input_t old_input, trigger_input;
|
retro_input_t old_input = last_input;
|
||||||
retro_input_t input = input_keys_pressed();
|
retro_input_t input = input_keys_pressed();
|
||||||
|
|
||||||
old_input = last_input;
|
|
||||||
last_input = input;
|
last_input = input;
|
||||||
|
|
||||||
if (driver.flushing_input)
|
if (driver.flushing_input)
|
||||||
|
@ -3258,6 +3261,7 @@ int rarch_main_iterate(void)
|
||||||
if (!menu_iterate(input, old_input, trigger_input))
|
if (!menu_iterate(input, old_input, trigger_input))
|
||||||
rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED);
|
rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED);
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3274,9 +3278,7 @@ int rarch_main_iterate(void)
|
||||||
driver.retro_ctx.poll_cb();
|
driver.retro_ctx.poll_cb();
|
||||||
rarch_sleep(10);
|
rarch_sleep(10);
|
||||||
|
|
||||||
/* TODO - maybe change this from 0 to something else
|
return 1;
|
||||||
* to signal that RetroArch is currently paused. */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_THREADS)
|
#if defined(HAVE_THREADS)
|
||||||
|
@ -3338,7 +3340,7 @@ success:
|
||||||
if (g_settings.fastforward_ratio_throttle_enable)
|
if (g_settings.fastforward_ratio_throttle_enable)
|
||||||
limit_frame_time();
|
limit_frame_time();
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rarch_main_deinit(void)
|
void rarch_main_deinit(void)
|
||||||
|
|
Loading…
Reference in New Issue