mirror of
https://github.com/libretro/RetroArch
synced 2025-03-23 19:21:03 +00:00
Move driver code to driver.c file - move code outside of retroarch.c
This commit is contained in:
parent
9e55654e72
commit
2d5e090eb3
@ -234,6 +234,7 @@ endif
|
||||
|
||||
OBJ += frontend/frontend_driver.o \
|
||||
retroarch.o \
|
||||
driver.o \
|
||||
camera/camera_driver.o \
|
||||
record/record_driver.o \
|
||||
command.o \
|
||||
|
@ -73,6 +73,8 @@ bool driver_bluetooth_connect_device(unsigned i);
|
||||
|
||||
bool bluetooth_driver_ctl(enum rarch_bluetooth_ctl_state state, void *data);
|
||||
|
||||
extern const bluetooth_driver_t *bluetooth_drivers[];
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
910
driver.c
Normal file
910
driver.c
Normal file
@ -0,0 +1,910 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2021 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "core_info.h"
|
||||
#include "driver.h"
|
||||
#include "retroarch.h"
|
||||
#include "runloop.h"
|
||||
#include "verbosity.h"
|
||||
|
||||
#include "bluetooth/bluetooth_driver.h"
|
||||
#include "wifi/wifi_driver.h"
|
||||
#include "led/led_driver.h"
|
||||
#include "midi_driver.h"
|
||||
#include "gfx/video_driver.h"
|
||||
#include "gfx/video_display_server.h"
|
||||
#include "audio/audio_driver.h"
|
||||
#include "camera/camera_driver.h"
|
||||
#include "record/record_driver.h"
|
||||
#include "location_driver.h"
|
||||
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
#include "gfx/gfx_widgets.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#include "menu/menu_driver.h"
|
||||
#endif
|
||||
|
||||
static bluetooth_driver_t bluetooth_null = {
|
||||
NULL, /* init */
|
||||
NULL, /* free */
|
||||
NULL, /* scan */
|
||||
NULL, /* get_devices */
|
||||
NULL, /* device_is_connected */
|
||||
NULL, /* device_get_sublabel */
|
||||
NULL, /* connect_device */
|
||||
"null",
|
||||
};
|
||||
|
||||
const bluetooth_driver_t *bluetooth_drivers[] = {
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
&bluetooth_bluetoothctl,
|
||||
#ifdef HAVE_DBUS
|
||||
&bluetooth_bluez,
|
||||
#endif
|
||||
#endif
|
||||
&bluetooth_null,
|
||||
NULL,
|
||||
};
|
||||
|
||||
wifi_driver_t wifi_null = {
|
||||
NULL, /* init */
|
||||
NULL, /* free */
|
||||
NULL, /* start */
|
||||
NULL, /* stop */
|
||||
NULL, /* enable */
|
||||
NULL, /* connection_info */
|
||||
NULL, /* scan */
|
||||
NULL, /* get_ssids */
|
||||
NULL, /* ssid_is_online */
|
||||
NULL, /* connect_ssid */
|
||||
NULL, /* disconnect_ssid */
|
||||
NULL, /* tether_start_stop */
|
||||
"null",
|
||||
};
|
||||
|
||||
const wifi_driver_t *wifi_drivers[] = {
|
||||
#ifdef HAVE_LAKKA
|
||||
&wifi_connmanctl,
|
||||
#endif
|
||||
#ifdef HAVE_WIFI
|
||||
&wifi_nmcli,
|
||||
#endif
|
||||
&wifi_null,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void retro_frame_null(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch) { }
|
||||
void retro_input_poll_null(void) { }
|
||||
|
||||
/**
|
||||
* find_driver_nonempty:
|
||||
* @label : string of driver type to be found.
|
||||
* @i : index of driver.
|
||||
* @str : identifier name of the found driver
|
||||
* gets written to this string.
|
||||
* @len : size of @str.
|
||||
*
|
||||
* Find driver based on @label.
|
||||
*
|
||||
* Returns: NULL if no driver based on @label found, otherwise
|
||||
* pointer to driver.
|
||||
**/
|
||||
static const void *find_driver_nonempty(
|
||||
const char *label, int i,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (string_is_equal(label, "camera_driver"))
|
||||
{
|
||||
if (camera_drivers[i])
|
||||
{
|
||||
const char *ident = camera_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return camera_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "location_driver"))
|
||||
{
|
||||
if (location_drivers[i])
|
||||
{
|
||||
const char *ident = location_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return location_drivers[i];
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MENU
|
||||
else if (string_is_equal(label, "menu_driver"))
|
||||
{
|
||||
if (menu_ctx_drivers[i])
|
||||
{
|
||||
const char *ident = menu_ctx_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return menu_ctx_drivers[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (string_is_equal(label, "input_driver"))
|
||||
{
|
||||
if (input_drivers[i])
|
||||
{
|
||||
const char *ident = input_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return input_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "input_joypad_driver"))
|
||||
{
|
||||
if (joypad_drivers[i])
|
||||
{
|
||||
const char *ident = joypad_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return joypad_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "video_driver"))
|
||||
{
|
||||
if (video_drivers[i])
|
||||
{
|
||||
const char *ident = video_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return video_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "audio_driver"))
|
||||
{
|
||||
if (audio_drivers[i])
|
||||
{
|
||||
const char *ident = audio_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return audio_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "record_driver"))
|
||||
{
|
||||
if (record_drivers[i])
|
||||
{
|
||||
const char *ident = record_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return record_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "midi_driver"))
|
||||
{
|
||||
if (midi_driver_find_handle(i))
|
||||
{
|
||||
const char *ident = midi_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return midi_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "audio_resampler_driver"))
|
||||
{
|
||||
if (audio_resampler_driver_find_handle(i))
|
||||
{
|
||||
const char *ident = audio_resampler_driver_find_ident(i);
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return audio_resampler_driver_find_handle(i);
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "bluetooth_driver"))
|
||||
{
|
||||
if (bluetooth_drivers[i])
|
||||
{
|
||||
const char *ident = bluetooth_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return bluetooth_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "wifi_driver"))
|
||||
{
|
||||
if (wifi_drivers[i])
|
||||
{
|
||||
const char *ident = wifi_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return wifi_drivers[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int driver_find_index(const char *label, const char *drv)
|
||||
{
|
||||
unsigned i;
|
||||
char str[NAME_MAX_LENGTH];
|
||||
|
||||
str[0] = '\0';
|
||||
|
||||
for (i = 0;
|
||||
find_driver_nonempty(label, i, str, sizeof(str)) != NULL; i++)
|
||||
{
|
||||
if (string_is_empty(str))
|
||||
break;
|
||||
if (string_is_equal_noncase(drv, str))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_find_last:
|
||||
* @label : string of driver type to be found.
|
||||
* @s : identifier of driver to be found.
|
||||
* @len : size of @s.
|
||||
*
|
||||
* Find last driver in driver array.
|
||||
**/
|
||||
static void driver_find_last(const char *label, char *s, size_t len)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0;
|
||||
find_driver_nonempty(label, i, s, len) != NULL; i++) { }
|
||||
|
||||
if (i)
|
||||
i = i - 1;
|
||||
else
|
||||
i = 0;
|
||||
|
||||
find_driver_nonempty(label, i, s, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_find_prev:
|
||||
* @label : string of driver type to be found.
|
||||
* @s : identifier of driver to be found.
|
||||
* @len : size of @s.
|
||||
*
|
||||
* Find previous driver in driver array.
|
||||
**/
|
||||
static bool driver_find_prev(const char *label, char *s, size_t len)
|
||||
{
|
||||
int i = driver_find_index(label, s);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
find_driver_nonempty(label, i - 1, s, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
RARCH_WARN(
|
||||
"Couldn't find any previous driver (current one: \"%s\").\n", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_find_next:
|
||||
* @label : string of driver type to be found.
|
||||
* @s : identifier of driver to be found.
|
||||
* @len : size of @s.
|
||||
*
|
||||
* Find next driver in driver array.
|
||||
**/
|
||||
static bool driver_find_next(const char *label, char *s, size_t len)
|
||||
{
|
||||
int i = driver_find_index(label, s);
|
||||
|
||||
if (i >= 0 && string_is_not_equal(s, "null"))
|
||||
{
|
||||
find_driver_nonempty(label, i + 1, s, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
RARCH_WARN("%s (current one: \"%s\").\n",
|
||||
msg_hash_to_str(MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER),
|
||||
s);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void driver_adjust_system_rates(
|
||||
bool vrr_runloop_enable,
|
||||
float video_refresh_rate,
|
||||
float audio_max_timing_skew,
|
||||
bool video_adaptive_vsync,
|
||||
unsigned video_swap_interval)
|
||||
{
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||
const struct retro_system_timing *info =
|
||||
(const struct retro_system_timing*)&av_info->timing;
|
||||
double input_sample_rate = info->sample_rate;
|
||||
double input_fps = info->fps;
|
||||
|
||||
if (input_sample_rate > 0.0)
|
||||
{
|
||||
audio_driver_state_t *audio_st = audio_state_get_ptr();
|
||||
if (vrr_runloop_enable)
|
||||
audio_st->input = input_sample_rate;
|
||||
else
|
||||
audio_st->input =
|
||||
audio_driver_monitor_adjust_system_rates(
|
||||
input_sample_rate,
|
||||
input_fps,
|
||||
video_refresh_rate,
|
||||
video_swap_interval,
|
||||
audio_max_timing_skew);
|
||||
|
||||
RARCH_LOG("[Audio]: Set audio input rate to: %.2f Hz.\n",
|
||||
audio_st->input);
|
||||
}
|
||||
|
||||
runloop_st->force_nonblock = false;
|
||||
|
||||
if (input_fps > 0.0)
|
||||
{
|
||||
float timing_skew_hz = video_refresh_rate;
|
||||
|
||||
if (video_st->crt_switching_active)
|
||||
timing_skew_hz = input_fps;
|
||||
video_st->core_hz = input_fps;
|
||||
|
||||
if (!video_driver_monitor_adjust_system_rates(
|
||||
timing_skew_hz,
|
||||
video_refresh_rate,
|
||||
vrr_runloop_enable,
|
||||
audio_max_timing_skew,
|
||||
input_fps))
|
||||
{
|
||||
/* We won't be able to do VSync reliably
|
||||
when game FPS > monitor FPS. */
|
||||
runloop_st->force_nonblock = true;
|
||||
RARCH_LOG("[Video]: Game FPS > Monitor FPS. Cannot rely on VSync.\n");
|
||||
|
||||
if (VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
|
||||
{
|
||||
if (video_st->current_video->set_nonblock_state)
|
||||
video_st->current_video->set_nonblock_state(
|
||||
video_st->data, true,
|
||||
video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
|
||||
video_adaptive_vsync,
|
||||
video_swap_interval
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
|
||||
driver_set_nonblock_state();
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_set_nonblock_state:
|
||||
*
|
||||
* Sets audio and video drivers to nonblock state (if enabled).
|
||||
*
|
||||
* If nonblock state is false, sets
|
||||
* blocking state for both audio and video drivers instead.
|
||||
**/
|
||||
void driver_set_nonblock_state(void)
|
||||
{
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
input_driver_state_t
|
||||
*input_st = input_state_get_ptr();
|
||||
audio_driver_state_t
|
||||
*audio_st = audio_state_get_ptr();
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
bool enable = input_st ?
|
||||
input_st->nonblocking_flag : false;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool audio_sync = settings->bools.audio_sync;
|
||||
bool video_vsync = settings->bools.video_vsync;
|
||||
bool adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned swap_interval = settings->uints.video_swap_interval;
|
||||
bool video_driver_active = video_st->active;
|
||||
bool audio_driver_active = audio_st->active;
|
||||
bool runloop_force_nonblock = runloop_st->force_nonblock;
|
||||
|
||||
/* Only apply non-block-state for video if we're using vsync. */
|
||||
if (video_driver_active && VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
|
||||
{
|
||||
if (video_st->current_video->set_nonblock_state)
|
||||
{
|
||||
bool video_nonblock = enable;
|
||||
if (!video_vsync || runloop_force_nonblock)
|
||||
video_nonblock = true;
|
||||
video_st->current_video->set_nonblock_state(video_st->data,
|
||||
video_nonblock,
|
||||
video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
|
||||
adaptive_vsync, swap_interval);
|
||||
}
|
||||
}
|
||||
|
||||
if (audio_driver_active && audio_st->context_audio_data)
|
||||
audio_st->current_audio->set_nonblock_state(
|
||||
audio_st->context_audio_data,
|
||||
audio_sync ? enable : true);
|
||||
|
||||
audio_st->chunk_size = enable
|
||||
? audio_st->chunk_nonblock_size
|
||||
: audio_st->chunk_block_size;
|
||||
}
|
||||
|
||||
void drivers_init(
|
||||
settings_t *settings,
|
||||
int flags,
|
||||
bool verbosity_enabled)
|
||||
{
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
audio_driver_state_t
|
||||
*audio_st = audio_state_get_ptr();
|
||||
input_driver_state_t
|
||||
*input_st = input_state_get_ptr();
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
#ifdef HAVE_MENU
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
#endif
|
||||
camera_driver_state_t
|
||||
*camera_st = camera_state_get_ptr();
|
||||
location_driver_state_t
|
||||
*location_st = location_state_get_ptr();
|
||||
bool video_is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
gfx_display_t *p_disp = disp_get_ptr();
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
bool video_font_enable = settings->bools.video_font_enable;
|
||||
bool menu_enable_widgets = settings->bools.menu_enable_widgets;
|
||||
|
||||
/* By default, we want display widgets to persist through driver reinits. */
|
||||
dispwidget_get_ptr()->persisting = true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
/* By default, we want the menu to persist through driver reinits. */
|
||||
if (menu_st)
|
||||
menu_st->data_own = true;
|
||||
#endif
|
||||
|
||||
if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
|
||||
driver_adjust_system_rates(
|
||||
settings->bools.vrr_runloop_enable,
|
||||
settings->floats.video_refresh_rate,
|
||||
settings->floats.audio_max_timing_skew,
|
||||
settings->bools.video_adaptive_vsync,
|
||||
settings->uints.video_swap_interval
|
||||
);
|
||||
|
||||
/* Initialize video driver */
|
||||
if (flags & DRIVER_VIDEO_MASK)
|
||||
{
|
||||
struct retro_hw_render_callback *hwr =
|
||||
VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st);
|
||||
|
||||
video_st->frame_time_count = 0;
|
||||
|
||||
video_driver_lock_new();
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
video_driver_filter_free();
|
||||
#endif
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
if (!video_driver_init_internal(&video_is_threaded,
|
||||
verbosity_enabled))
|
||||
retroarch_fail(1, "video_driver_init_internal()");
|
||||
|
||||
if (!video_st->cache_context_ack
|
||||
&& hwr->context_reset)
|
||||
hwr->context_reset();
|
||||
video_st->cache_context_ack = false;
|
||||
runloop_st->frame_time_last = 0;
|
||||
}
|
||||
|
||||
/* Initialize audio driver */
|
||||
if (flags & DRIVER_AUDIO_MASK)
|
||||
{
|
||||
audio_driver_init_internal(
|
||||
settings,
|
||||
audio_st->callback.callback != NULL);
|
||||
if ( audio_st->current_audio &&
|
||||
audio_st->current_audio->device_list_new &&
|
||||
audio_st->context_audio_data)
|
||||
audio_st->devices_list = (struct string_list*)
|
||||
audio_st->current_audio->device_list_new(
|
||||
audio_st->context_audio_data);
|
||||
}
|
||||
|
||||
if (flags & DRIVER_CAMERA_MASK)
|
||||
{
|
||||
/* Only initialize camera driver if we're ever going to use it. */
|
||||
if (camera_st->active)
|
||||
{
|
||||
/* Resource leaks will follow if camera is initialized twice. */
|
||||
if (!camera_st->data)
|
||||
{
|
||||
if (!camera_driver_find_driver("camera driver",
|
||||
verbosity_enabled))
|
||||
retroarch_fail(1, "find_camera_driver()");
|
||||
|
||||
if (camera_st->driver)
|
||||
{
|
||||
camera_st->data = camera_st->driver->init(
|
||||
*settings->arrays.camera_device ?
|
||||
settings->arrays.camera_device : NULL,
|
||||
camera_st->cb.caps,
|
||||
settings->uints.camera_width ?
|
||||
settings->uints.camera_width : camera_st->cb.width,
|
||||
settings->uints.camera_height ?
|
||||
settings->uints.camera_height : camera_st->cb.height);
|
||||
|
||||
if (!camera_st->data)
|
||||
{
|
||||
RARCH_ERR("Failed to initialize camera driver. Will continue without camera.\n");
|
||||
camera_st->active = false;
|
||||
}
|
||||
|
||||
if (camera_st->cb.initialized)
|
||||
camera_st->cb.initialized();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DRIVER_BLUETOOTH_MASK)
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_INIT, NULL);
|
||||
|
||||
if ((flags & DRIVER_WIFI_MASK))
|
||||
wifi_driver_ctl(RARCH_WIFI_CTL_INIT, NULL);
|
||||
|
||||
if (flags & DRIVER_LOCATION_MASK)
|
||||
{
|
||||
/* Only initialize location driver if we're ever going to use it. */
|
||||
if (location_st->active)
|
||||
if (!init_location(&runloop_state_get_ptr()->system,
|
||||
settings, verbosity_is_enabled()))
|
||||
location_st->active = false;
|
||||
}
|
||||
|
||||
core_info_init_current_core();
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* Note that we only enable widgets if 'video_font_enable'
|
||||
* is true. 'video_font_enable' corresponds to the generic
|
||||
* 'On-Screen Notifications' setting, which should serve as
|
||||
* a global notifications on/off toggle switch */
|
||||
if (video_font_enable &&
|
||||
menu_enable_widgets &&
|
||||
video_driver_has_widgets())
|
||||
{
|
||||
bool rarch_force_fullscreen = video_st->force_fullscreen;
|
||||
bool video_is_fullscreen = settings->bools.video_fullscreen ||
|
||||
rarch_force_fullscreen;
|
||||
|
||||
dispwidget_get_ptr()->active= gfx_widgets_init(
|
||||
p_disp,
|
||||
anim_get_ptr(),
|
||||
settings,
|
||||
(uintptr_t)&dispwidget_get_ptr()->active,
|
||||
video_is_threaded,
|
||||
video_st->width,
|
||||
video_st->height,
|
||||
video_is_fullscreen,
|
||||
settings->paths.directory_assets,
|
||||
settings->paths.path_font);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gfx_display_init_first_driver(p_disp, video_is_threaded);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
if (flags & DRIVER_VIDEO_MASK)
|
||||
{
|
||||
/* Initialize menu driver */
|
||||
if (flags & DRIVER_MENU_MASK)
|
||||
{
|
||||
if (!menu_driver_init(video_is_threaded))
|
||||
RARCH_ERR("Unable to init menu driver.\n");
|
||||
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
menu_explore_context_init();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialising the menu driver will also initialise
|
||||
* core info - if we are not initialising the menu
|
||||
* driver, must initialise core info 'by hand' */
|
||||
if (!(flags & DRIVER_VIDEO_MASK) ||
|
||||
!(flags & DRIVER_MENU_MASK))
|
||||
{
|
||||
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
|
||||
command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
/* Qt uses core info, even if the menu is disabled */
|
||||
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
|
||||
command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
|
||||
#endif
|
||||
|
||||
/* Keep non-throttled state as good as possible. */
|
||||
if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
|
||||
if (input_st && input_st->nonblocking_flag)
|
||||
driver_set_nonblock_state();
|
||||
|
||||
/* Initialize LED driver */
|
||||
if (flags & DRIVER_LED_MASK)
|
||||
led_driver_init(settings->arrays.led_driver);
|
||||
|
||||
/* Initialize MIDI driver */
|
||||
if (flags & DRIVER_MIDI_MASK)
|
||||
midi_driver_init(settings);
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
cpu_scaling_driver_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void driver_uninit(int flags)
|
||||
{
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
camera_driver_state_t
|
||||
*camera_st = camera_state_get_ptr();
|
||||
|
||||
core_info_deinit_list();
|
||||
core_info_free_current_core();
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* This absolutely has to be done before video_driver_free_internal()
|
||||
* is called/completes, otherwise certain menu drivers
|
||||
* (e.g. Vulkan) will segfault */
|
||||
if (dispwidget_get_ptr()->inited)
|
||||
{
|
||||
gfx_widgets_deinit(dispwidget_get_ptr()->persisting);
|
||||
dispwidget_get_ptr()->active = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
if (flags & DRIVER_MENU_MASK)
|
||||
{
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
menu_explore_context_deinit();
|
||||
#endif
|
||||
|
||||
menu_driver_ctl(RARCH_MENU_CTL_DEINIT, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((flags & DRIVER_LOCATION_MASK))
|
||||
uninit_location(&runloop_st->system);
|
||||
|
||||
if ((flags & DRIVER_CAMERA_MASK))
|
||||
{
|
||||
if (camera_st->data && camera_st->driver)
|
||||
{
|
||||
if (camera_st->cb.deinitialized)
|
||||
camera_st->cb.deinitialized();
|
||||
|
||||
if (camera_st->driver->free)
|
||||
camera_st->driver->free(camera_st->data);
|
||||
}
|
||||
|
||||
camera_st->data = NULL;
|
||||
}
|
||||
|
||||
if ((flags & DRIVER_BLUETOOTH_MASK))
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DEINIT, NULL);
|
||||
|
||||
if ((flags & DRIVER_WIFI_MASK))
|
||||
wifi_driver_ctl(RARCH_WIFI_CTL_DEINIT, NULL);
|
||||
|
||||
if (flags & DRIVER_LED)
|
||||
led_driver_free();
|
||||
|
||||
if (flags & DRIVERS_VIDEO_INPUT)
|
||||
{
|
||||
video_driver_free_internal();
|
||||
VIDEO_DRIVER_LOCK_FREE(video_st);
|
||||
video_st->data = NULL;
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
}
|
||||
|
||||
if (flags & DRIVER_AUDIO_MASK)
|
||||
audio_driver_deinit();
|
||||
|
||||
if ((flags & DRIVER_VIDEO_MASK))
|
||||
video_st->data = NULL;
|
||||
|
||||
if ((flags & DRIVER_INPUT_MASK))
|
||||
input_state_get_ptr()->current_data = NULL;
|
||||
|
||||
if ((flags & DRIVER_AUDIO_MASK))
|
||||
audio_state_get_ptr()->context_audio_data = NULL;
|
||||
|
||||
if (flags & DRIVER_MIDI_MASK)
|
||||
midi_driver_free();
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
cpu_scaling_driver_free();
|
||||
#endif
|
||||
}
|
||||
|
||||
void retroarch_deinit_drivers(struct retro_callbacks *cbs)
|
||||
{
|
||||
input_driver_state_t *input_st = input_state_get_ptr();
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
camera_driver_state_t *camera_st= camera_state_get_ptr();
|
||||
location_driver_state_t
|
||||
*location_st = location_state_get_ptr();
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* Tear down display widgets no matter what
|
||||
* in case the handle is lost in the threaded
|
||||
* video driver in the meantime
|
||||
* (breaking video_driver_has_widgets) */
|
||||
if (dispwidget_get_ptr()->inited)
|
||||
{
|
||||
gfx_widgets_deinit(
|
||||
dispwidget_get_ptr()->persisting);
|
||||
dispwidget_get_ptr()->active = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CRTSWITCHRES)
|
||||
/* Switchres deinit */
|
||||
if (video_st->crt_switching_active)
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
RARCH_LOG("[CRT]: Getting video info\n");
|
||||
RARCH_LOG("[CRT]: About to destroy SR\n");
|
||||
#endif
|
||||
crt_destroy_modes(&video_st->crt_switch_st);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Video */
|
||||
video_display_server_destroy();
|
||||
|
||||
video_st->use_rgba = false;
|
||||
video_st->hdr_support = false;
|
||||
video_st->active = false;
|
||||
video_st->cache_context = false;
|
||||
video_st->cache_context_ack = false;
|
||||
video_st->record_gpu_buffer = NULL;
|
||||
video_st->current_video = NULL;
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
|
||||
/* Audio */
|
||||
audio_state_get_ptr()->active = false;
|
||||
audio_state_get_ptr()->current_audio = NULL;
|
||||
|
||||
/* Input */
|
||||
input_st->keyboard_linefeed_enable = false;
|
||||
input_st->block_hotkey = false;
|
||||
input_st->block_libretro_input = false;
|
||||
|
||||
if (input_st)
|
||||
input_st->nonblocking_flag = false;
|
||||
|
||||
memset(&input_st->turbo_btns, 0, sizeof(turbo_buttons_t));
|
||||
memset(&input_st->analog_requested, 0,
|
||||
sizeof(input_st->analog_requested));
|
||||
input_st->current_driver = NULL;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
menu_driver_destroy(
|
||||
menu_state_get_ptr());
|
||||
#endif
|
||||
location_st->active = false;
|
||||
destroy_location();
|
||||
|
||||
/* Camera */
|
||||
camera_st->active = false;
|
||||
camera_st->driver = NULL;
|
||||
camera_st->data = NULL;
|
||||
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DESTROY, NULL);
|
||||
wifi_driver_ctl(RARCH_WIFI_CTL_DESTROY, NULL);
|
||||
|
||||
cbs->frame_cb = retro_frame_null;
|
||||
cbs->poll_cb = retro_input_poll_null;
|
||||
cbs->sample_cb = NULL;
|
||||
cbs->sample_batch_cb = NULL;
|
||||
cbs->state_cb = NULL;
|
||||
|
||||
runloop_st->current_core.inited = false;
|
||||
}
|
||||
|
||||
bool driver_ctl(enum driver_ctl_state state, void *data)
|
||||
{
|
||||
driver_ctx_info_t *drv = (driver_ctx_info_t*)data;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case RARCH_DRIVER_CTL_SET_REFRESH_RATE:
|
||||
{
|
||||
float *hz = (float*)data;
|
||||
audio_driver_state_t
|
||||
*audio_st = audio_state_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned
|
||||
audio_output_sample_rate = settings->uints.audio_output_sample_rate;
|
||||
bool vrr_runloop_enable = settings->bools.vrr_runloop_enable;
|
||||
float video_refresh_rate = settings->floats.video_refresh_rate;
|
||||
float audio_max_timing_skew = settings->floats.audio_max_timing_skew;
|
||||
bool video_adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned video_swap_interval = settings->uints.video_swap_interval;
|
||||
|
||||
video_monitor_set_refresh_rate(*hz);
|
||||
|
||||
/* Sets audio monitor rate to new value. */
|
||||
audio_st->source_ratio_original =
|
||||
audio_st->source_ratio_current =
|
||||
(double)audio_output_sample_rate / audio_st->input;
|
||||
|
||||
driver_adjust_system_rates(
|
||||
vrr_runloop_enable,
|
||||
video_refresh_rate,
|
||||
audio_max_timing_skew,
|
||||
video_adaptive_vsync,
|
||||
video_swap_interval
|
||||
);
|
||||
}
|
||||
break;
|
||||
case RARCH_DRIVER_CTL_FIND_FIRST:
|
||||
if (!drv)
|
||||
return false;
|
||||
find_driver_nonempty(drv->label, 0, drv->s, drv->len);
|
||||
break;
|
||||
case RARCH_DRIVER_CTL_FIND_LAST:
|
||||
if (!drv)
|
||||
return false;
|
||||
driver_find_last(drv->label, drv->s, drv->len);
|
||||
break;
|
||||
case RARCH_DRIVER_CTL_FIND_PREV:
|
||||
if (!drv)
|
||||
return false;
|
||||
return driver_find_prev(drv->label, drv->s, drv->len);
|
||||
case RARCH_DRIVER_CTL_FIND_NEXT:
|
||||
if (!drv)
|
||||
return false;
|
||||
return driver_find_next(drv->label, drv->s, drv->len);
|
||||
case RARCH_DRIVER_CTL_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
5
driver.h
5
driver.h
@ -25,6 +25,7 @@
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include "configuration.h"
|
||||
#include "retroarch_types.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
@ -130,6 +131,10 @@ void drivers_init(settings_t *settings, int flags,
|
||||
**/
|
||||
void driver_uninit(int flags);
|
||||
|
||||
void retro_input_poll_null(void);
|
||||
|
||||
void retroarch_deinit_drivers(struct retro_callbacks *cbs);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -1219,6 +1219,7 @@ RETROARCH
|
||||
============================================================ */
|
||||
#include "../retroarch.c"
|
||||
#include "../command.c"
|
||||
#include "../driver.c"
|
||||
#include "../midi_driver.c"
|
||||
#include "../location_driver.c"
|
||||
#include "../libretro-common/queues/task_queue.c"
|
||||
|
882
retroarch.c
882
retroarch.c
@ -390,54 +390,8 @@
|
||||
#endif
|
||||
|
||||
/* DRIVERS */
|
||||
static bluetooth_driver_t bluetooth_null = {
|
||||
NULL, /* init */
|
||||
NULL, /* free */
|
||||
NULL, /* scan */
|
||||
NULL, /* get_devices */
|
||||
NULL, /* device_is_connected */
|
||||
NULL, /* device_get_sublabel */
|
||||
NULL, /* connect_device */
|
||||
"null",
|
||||
};
|
||||
|
||||
static const bluetooth_driver_t *bluetooth_drivers[] = {
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
&bluetooth_bluetoothctl,
|
||||
#ifdef HAVE_DBUS
|
||||
&bluetooth_bluez,
|
||||
#endif
|
||||
#endif
|
||||
&bluetooth_null,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static wifi_driver_t wifi_null = {
|
||||
NULL, /* init */
|
||||
NULL, /* free */
|
||||
NULL, /* start */
|
||||
NULL, /* stop */
|
||||
NULL, /* enable */
|
||||
NULL, /* connection_info */
|
||||
NULL, /* scan */
|
||||
NULL, /* get_ssids */
|
||||
NULL, /* ssid_is_online */
|
||||
NULL, /* connect_ssid */
|
||||
NULL, /* disconnect_ssid */
|
||||
NULL, /* tether_start_stop */
|
||||
"null",
|
||||
};
|
||||
|
||||
static const wifi_driver_t *wifi_drivers[] = {
|
||||
#ifdef HAVE_LAKKA
|
||||
&wifi_connmanctl,
|
||||
#endif
|
||||
#ifdef HAVE_WIFI
|
||||
&wifi_nmcli,
|
||||
#endif
|
||||
&wifi_null,
|
||||
NULL,
|
||||
};
|
||||
extern const bluetooth_driver_t *bluetooth_drivers[];
|
||||
|
||||
static ui_companion_driver_t ui_companion_null = {
|
||||
NULL, /* init */
|
||||
@ -537,14 +491,10 @@ struct rarch_state
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
static void retroarch_fail(int error_code, const char *error);
|
||||
|
||||
#ifdef HAVE_LIBNX
|
||||
void libnx_apply_overclock(void);
|
||||
#endif
|
||||
|
||||
static void retroarch_deinit_drivers(struct retro_callbacks *cbs);
|
||||
|
||||
#ifdef HAVE_RUNAHEAD
|
||||
#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
|
||||
static bool secondary_core_create(runloop_state_t *runloop_st, settings_t *settings);
|
||||
@ -555,10 +505,7 @@ static bool secondary_core_ensure_exists(
|
||||
static int16_t input_state_get_last(unsigned port,
|
||||
unsigned device, unsigned index, unsigned id);
|
||||
#endif
|
||||
static void retro_frame_null(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch);
|
||||
static void retro_run_null(void);
|
||||
static void retro_input_poll_null(void);
|
||||
static void runloop_apply_fastmotion_override(runloop_state_t *p_runloop, settings_t *settings);
|
||||
|
||||
static void uninit_libretro_symbols(struct retro_core_t *current_core);
|
||||
@ -580,10 +527,6 @@ static void ui_companion_driver_init_first(struct rarch_state *p_rarch);
|
||||
static bool core_load(unsigned poll_type_behavior);
|
||||
static bool core_unload_game(void);
|
||||
|
||||
static const void *find_driver_nonempty(
|
||||
const char *label, int i,
|
||||
char *s, size_t len);
|
||||
|
||||
static struct rarch_state rarch_st = {0};
|
||||
|
||||
#ifdef HAVE_THREAD_STORAGE
|
||||
@ -633,240 +576,6 @@ global_t *global_get_ptr(void)
|
||||
return &p_rarch->g_extern;
|
||||
}
|
||||
|
||||
/* DRIVERS */
|
||||
|
||||
int driver_find_index(const char *label, const char *drv)
|
||||
{
|
||||
unsigned i;
|
||||
char str[NAME_MAX_LENGTH];
|
||||
|
||||
str[0] = '\0';
|
||||
|
||||
for (i = 0;
|
||||
find_driver_nonempty(label, i, str, sizeof(str)) != NULL; i++)
|
||||
{
|
||||
if (string_is_empty(str))
|
||||
break;
|
||||
if (string_is_equal_noncase(drv, str))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_find_last:
|
||||
* @label : string of driver type to be found.
|
||||
* @s : identifier of driver to be found.
|
||||
* @len : size of @s.
|
||||
*
|
||||
* Find last driver in driver array.
|
||||
**/
|
||||
static void driver_find_last(const char *label, char *s, size_t len)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0;
|
||||
find_driver_nonempty(label, i, s, len) != NULL; i++) { }
|
||||
|
||||
if (i)
|
||||
i = i - 1;
|
||||
else
|
||||
i = 0;
|
||||
|
||||
find_driver_nonempty(label, i, s, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_find_prev:
|
||||
* @label : string of driver type to be found.
|
||||
* @s : identifier of driver to be found.
|
||||
* @len : size of @s.
|
||||
*
|
||||
* Find previous driver in driver array.
|
||||
**/
|
||||
static bool driver_find_prev(const char *label, char *s, size_t len)
|
||||
{
|
||||
int i = driver_find_index(label, s);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
find_driver_nonempty(label, i - 1, s, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
RARCH_WARN(
|
||||
"Couldn't find any previous driver (current one: \"%s\").\n", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_find_next:
|
||||
* @label : string of driver type to be found.
|
||||
* @s : identifier of driver to be found.
|
||||
* @len : size of @s.
|
||||
*
|
||||
* Find next driver in driver array.
|
||||
**/
|
||||
static bool driver_find_next(const char *label, char *s, size_t len)
|
||||
{
|
||||
int i = driver_find_index(label, s);
|
||||
|
||||
if (i >= 0 && string_is_not_equal(s, "null"))
|
||||
{
|
||||
find_driver_nonempty(label, i + 1, s, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
RARCH_WARN("%s (current one: \"%s\").\n",
|
||||
msg_hash_to_str(MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER),
|
||||
s);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_driver_nonempty:
|
||||
* @label : string of driver type to be found.
|
||||
* @i : index of driver.
|
||||
* @str : identifier name of the found driver
|
||||
* gets written to this string.
|
||||
* @len : size of @str.
|
||||
*
|
||||
* Find driver based on @label.
|
||||
*
|
||||
* Returns: NULL if no driver based on @label found, otherwise
|
||||
* pointer to driver.
|
||||
**/
|
||||
static const void *find_driver_nonempty(
|
||||
const char *label, int i,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (string_is_equal(label, "camera_driver"))
|
||||
{
|
||||
if (camera_drivers[i])
|
||||
{
|
||||
const char *ident = camera_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return camera_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "location_driver"))
|
||||
{
|
||||
if (location_drivers[i])
|
||||
{
|
||||
const char *ident = location_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return location_drivers[i];
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MENU
|
||||
else if (string_is_equal(label, "menu_driver"))
|
||||
{
|
||||
if (menu_ctx_drivers[i])
|
||||
{
|
||||
const char *ident = menu_ctx_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return menu_ctx_drivers[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (string_is_equal(label, "input_driver"))
|
||||
{
|
||||
if (input_drivers[i])
|
||||
{
|
||||
const char *ident = input_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return input_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "input_joypad_driver"))
|
||||
{
|
||||
if (joypad_drivers[i])
|
||||
{
|
||||
const char *ident = joypad_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return joypad_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "video_driver"))
|
||||
{
|
||||
if (video_drivers[i])
|
||||
{
|
||||
const char *ident = video_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return video_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "audio_driver"))
|
||||
{
|
||||
if (audio_drivers[i])
|
||||
{
|
||||
const char *ident = audio_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return audio_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "record_driver"))
|
||||
{
|
||||
if (record_drivers[i])
|
||||
{
|
||||
const char *ident = record_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return record_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "midi_driver"))
|
||||
{
|
||||
if (midi_driver_find_handle(i))
|
||||
{
|
||||
const char *ident = midi_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return midi_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "audio_resampler_driver"))
|
||||
{
|
||||
if (audio_resampler_driver_find_handle(i))
|
||||
{
|
||||
const char *ident = audio_resampler_driver_find_ident(i);
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return audio_resampler_driver_find_handle(i);
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "bluetooth_driver"))
|
||||
{
|
||||
if (bluetooth_drivers[i])
|
||||
{
|
||||
const char *ident = bluetooth_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return bluetooth_drivers[i];
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(label, "wifi_driver"))
|
||||
{
|
||||
if (wifi_drivers[i])
|
||||
{
|
||||
const char *ident = wifi_drivers[i]->ident;
|
||||
|
||||
strlcpy(s, ident, len);
|
||||
return wifi_drivers[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PERF_LOG_FMT "[PERF]: Avg (%s): %I64u ticks, %I64u runs.\n"
|
||||
#else
|
||||
@ -10796,583 +10505,6 @@ char* crt_switch_core_name(void)
|
||||
return (char*)runloop_state.system.info.library_name;
|
||||
}
|
||||
|
||||
static void driver_adjust_system_rates(
|
||||
bool vrr_runloop_enable,
|
||||
float video_refresh_rate,
|
||||
float audio_max_timing_skew,
|
||||
bool video_adaptive_vsync,
|
||||
unsigned video_swap_interval)
|
||||
{
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||
const struct retro_system_timing *info =
|
||||
(const struct retro_system_timing*)&av_info->timing;
|
||||
double input_sample_rate = info->sample_rate;
|
||||
double input_fps = info->fps;
|
||||
|
||||
if (input_sample_rate > 0.0)
|
||||
{
|
||||
audio_driver_state_t *audio_st = audio_state_get_ptr();
|
||||
if (vrr_runloop_enable)
|
||||
audio_st->input = input_sample_rate;
|
||||
else
|
||||
audio_st->input =
|
||||
audio_driver_monitor_adjust_system_rates(
|
||||
input_sample_rate,
|
||||
input_fps,
|
||||
video_refresh_rate,
|
||||
video_swap_interval,
|
||||
audio_max_timing_skew);
|
||||
|
||||
RARCH_LOG("[Audio]: Set audio input rate to: %.2f Hz.\n",
|
||||
audio_st->input);
|
||||
}
|
||||
|
||||
runloop_st->force_nonblock = false;
|
||||
|
||||
if (input_fps > 0.0)
|
||||
{
|
||||
float timing_skew_hz = video_refresh_rate;
|
||||
|
||||
if (video_st->crt_switching_active)
|
||||
timing_skew_hz = input_fps;
|
||||
video_st->core_hz = input_fps;
|
||||
|
||||
if (!video_driver_monitor_adjust_system_rates(
|
||||
timing_skew_hz,
|
||||
video_refresh_rate,
|
||||
vrr_runloop_enable,
|
||||
audio_max_timing_skew,
|
||||
input_fps))
|
||||
{
|
||||
/* We won't be able to do VSync reliably
|
||||
when game FPS > monitor FPS. */
|
||||
runloop_st->force_nonblock = true;
|
||||
RARCH_LOG("[Video]: Game FPS > Monitor FPS. Cannot rely on VSync.\n");
|
||||
|
||||
if (VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
|
||||
{
|
||||
if (video_st->current_video->set_nonblock_state)
|
||||
video_st->current_video->set_nonblock_state(
|
||||
video_st->data, true,
|
||||
video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
|
||||
video_adaptive_vsync,
|
||||
video_swap_interval
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
|
||||
driver_set_nonblock_state();
|
||||
}
|
||||
|
||||
/**
|
||||
* driver_set_nonblock_state:
|
||||
*
|
||||
* Sets audio and video drivers to nonblock state (if enabled).
|
||||
*
|
||||
* If nonblock state is false, sets
|
||||
* blocking state for both audio and video drivers instead.
|
||||
**/
|
||||
void driver_set_nonblock_state(void)
|
||||
{
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
input_driver_state_t
|
||||
*input_st = input_state_get_ptr();
|
||||
audio_driver_state_t
|
||||
*audio_st = audio_state_get_ptr();
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
bool enable = input_st ?
|
||||
input_st->nonblocking_flag : false;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool audio_sync = settings->bools.audio_sync;
|
||||
bool video_vsync = settings->bools.video_vsync;
|
||||
bool adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned swap_interval = settings->uints.video_swap_interval;
|
||||
bool video_driver_active = video_st->active;
|
||||
bool audio_driver_active = audio_st->active;
|
||||
bool runloop_force_nonblock = runloop_st->force_nonblock;
|
||||
|
||||
/* Only apply non-block-state for video if we're using vsync. */
|
||||
if (video_driver_active && VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
|
||||
{
|
||||
if (video_st->current_video->set_nonblock_state)
|
||||
{
|
||||
bool video_nonblock = enable;
|
||||
if (!video_vsync || runloop_force_nonblock)
|
||||
video_nonblock = true;
|
||||
video_st->current_video->set_nonblock_state(video_st->data,
|
||||
video_nonblock,
|
||||
video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
|
||||
adaptive_vsync, swap_interval);
|
||||
}
|
||||
}
|
||||
|
||||
if (audio_driver_active && audio_st->context_audio_data)
|
||||
audio_st->current_audio->set_nonblock_state(
|
||||
audio_st->context_audio_data,
|
||||
audio_sync ? enable : true);
|
||||
|
||||
audio_st->chunk_size = enable
|
||||
? audio_st->chunk_nonblock_size
|
||||
: audio_st->chunk_block_size;
|
||||
}
|
||||
|
||||
void drivers_init(
|
||||
settings_t *settings,
|
||||
int flags,
|
||||
bool verbosity_enabled)
|
||||
{
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
audio_driver_state_t
|
||||
*audio_st = audio_state_get_ptr();
|
||||
input_driver_state_t
|
||||
*input_st = input_state_get_ptr();
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
#ifdef HAVE_MENU
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
#endif
|
||||
camera_driver_state_t
|
||||
*camera_st = camera_state_get_ptr();
|
||||
location_driver_state_t
|
||||
*location_st = location_state_get_ptr();
|
||||
bool video_is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
gfx_display_t *p_disp = disp_get_ptr();
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
bool video_font_enable = settings->bools.video_font_enable;
|
||||
bool menu_enable_widgets = settings->bools.menu_enable_widgets;
|
||||
|
||||
/* By default, we want display widgets to persist through driver reinits. */
|
||||
dispwidget_get_ptr()->persisting = true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
/* By default, we want the menu to persist through driver reinits. */
|
||||
if (menu_st)
|
||||
menu_st->data_own = true;
|
||||
#endif
|
||||
|
||||
if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
|
||||
driver_adjust_system_rates(
|
||||
settings->bools.vrr_runloop_enable,
|
||||
settings->floats.video_refresh_rate,
|
||||
settings->floats.audio_max_timing_skew,
|
||||
settings->bools.video_adaptive_vsync,
|
||||
settings->uints.video_swap_interval
|
||||
);
|
||||
|
||||
/* Initialize video driver */
|
||||
if (flags & DRIVER_VIDEO_MASK)
|
||||
{
|
||||
struct retro_hw_render_callback *hwr =
|
||||
VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st);
|
||||
|
||||
video_st->frame_time_count = 0;
|
||||
|
||||
video_driver_lock_new();
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
video_driver_filter_free();
|
||||
#endif
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
if (!video_driver_init_internal(&video_is_threaded,
|
||||
verbosity_enabled))
|
||||
retroarch_fail(1, "video_driver_init_internal()");
|
||||
|
||||
if (!video_st->cache_context_ack
|
||||
&& hwr->context_reset)
|
||||
hwr->context_reset();
|
||||
video_st->cache_context_ack = false;
|
||||
runloop_st->frame_time_last = 0;
|
||||
}
|
||||
|
||||
/* Initialize audio driver */
|
||||
if (flags & DRIVER_AUDIO_MASK)
|
||||
{
|
||||
audio_driver_init_internal(
|
||||
settings,
|
||||
audio_st->callback.callback != NULL);
|
||||
if ( audio_st->current_audio &&
|
||||
audio_st->current_audio->device_list_new &&
|
||||
audio_st->context_audio_data)
|
||||
audio_st->devices_list = (struct string_list*)
|
||||
audio_st->current_audio->device_list_new(
|
||||
audio_st->context_audio_data);
|
||||
}
|
||||
|
||||
if (flags & DRIVER_CAMERA_MASK)
|
||||
{
|
||||
/* Only initialize camera driver if we're ever going to use it. */
|
||||
if (camera_st->active)
|
||||
{
|
||||
/* Resource leaks will follow if camera is initialized twice. */
|
||||
if (!camera_st->data)
|
||||
{
|
||||
if (!camera_driver_find_driver("camera driver",
|
||||
verbosity_enabled))
|
||||
retroarch_fail(1, "find_camera_driver()");
|
||||
|
||||
if (camera_st->driver)
|
||||
{
|
||||
camera_st->data = camera_st->driver->init(
|
||||
*settings->arrays.camera_device ?
|
||||
settings->arrays.camera_device : NULL,
|
||||
camera_st->cb.caps,
|
||||
settings->uints.camera_width ?
|
||||
settings->uints.camera_width : camera_st->cb.width,
|
||||
settings->uints.camera_height ?
|
||||
settings->uints.camera_height : camera_st->cb.height);
|
||||
|
||||
if (!camera_st->data)
|
||||
{
|
||||
RARCH_ERR("Failed to initialize camera driver. Will continue without camera.\n");
|
||||
camera_st->active = false;
|
||||
}
|
||||
|
||||
if (camera_st->cb.initialized)
|
||||
camera_st->cb.initialized();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DRIVER_BLUETOOTH_MASK)
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_INIT, NULL);
|
||||
|
||||
if ((flags & DRIVER_WIFI_MASK))
|
||||
wifi_driver_ctl(RARCH_WIFI_CTL_INIT, NULL);
|
||||
|
||||
if (flags & DRIVER_LOCATION_MASK)
|
||||
{
|
||||
/* Only initialize location driver if we're ever going to use it. */
|
||||
if (location_st->active)
|
||||
if (!init_location(&runloop_state.system,
|
||||
settings, verbosity_is_enabled()))
|
||||
location_st->active = false;
|
||||
}
|
||||
|
||||
core_info_init_current_core();
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* Note that we only enable widgets if 'video_font_enable'
|
||||
* is true. 'video_font_enable' corresponds to the generic
|
||||
* 'On-Screen Notifications' setting, which should serve as
|
||||
* a global notifications on/off toggle switch */
|
||||
if (video_font_enable &&
|
||||
menu_enable_widgets &&
|
||||
video_driver_has_widgets())
|
||||
{
|
||||
bool rarch_force_fullscreen = video_st->force_fullscreen;
|
||||
bool video_is_fullscreen = settings->bools.video_fullscreen ||
|
||||
rarch_force_fullscreen;
|
||||
|
||||
dispwidget_get_ptr()->active= gfx_widgets_init(
|
||||
p_disp,
|
||||
anim_get_ptr(),
|
||||
settings,
|
||||
(uintptr_t)&dispwidget_get_ptr()->active,
|
||||
video_is_threaded,
|
||||
video_st->width,
|
||||
video_st->height,
|
||||
video_is_fullscreen,
|
||||
settings->paths.directory_assets,
|
||||
settings->paths.path_font);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gfx_display_init_first_driver(p_disp, video_is_threaded);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
if (flags & DRIVER_VIDEO_MASK)
|
||||
{
|
||||
/* Initialize menu driver */
|
||||
if (flags & DRIVER_MENU_MASK)
|
||||
{
|
||||
if (!menu_driver_init(video_is_threaded))
|
||||
RARCH_ERR("Unable to init menu driver.\n");
|
||||
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
menu_explore_context_init();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialising the menu driver will also initialise
|
||||
* core info - if we are not initialising the menu
|
||||
* driver, must initialise core info 'by hand' */
|
||||
if (!(flags & DRIVER_VIDEO_MASK) ||
|
||||
!(flags & DRIVER_MENU_MASK))
|
||||
{
|
||||
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
|
||||
command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
/* Qt uses core info, even if the menu is disabled */
|
||||
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
|
||||
command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
|
||||
#endif
|
||||
|
||||
/* Keep non-throttled state as good as possible. */
|
||||
if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
|
||||
if (input_st && input_st->nonblocking_flag)
|
||||
driver_set_nonblock_state();
|
||||
|
||||
/* Initialize LED driver */
|
||||
if (flags & DRIVER_LED_MASK)
|
||||
led_driver_init(settings->arrays.led_driver);
|
||||
|
||||
/* Initialize MIDI driver */
|
||||
if (flags & DRIVER_MIDI_MASK)
|
||||
midi_driver_init(settings);
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
cpu_scaling_driver_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void driver_uninit(int flags)
|
||||
{
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
camera_driver_state_t
|
||||
*camera_st = camera_state_get_ptr();
|
||||
|
||||
core_info_deinit_list();
|
||||
core_info_free_current_core();
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* This absolutely has to be done before video_driver_free_internal()
|
||||
* is called/completes, otherwise certain menu drivers
|
||||
* (e.g. Vulkan) will segfault */
|
||||
if (dispwidget_get_ptr()->inited)
|
||||
{
|
||||
gfx_widgets_deinit(dispwidget_get_ptr()->persisting);
|
||||
dispwidget_get_ptr()->active = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
if (flags & DRIVER_MENU_MASK)
|
||||
{
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
menu_explore_context_deinit();
|
||||
#endif
|
||||
|
||||
menu_driver_ctl(RARCH_MENU_CTL_DEINIT, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((flags & DRIVER_LOCATION_MASK))
|
||||
uninit_location(&runloop_st->system);
|
||||
|
||||
if ((flags & DRIVER_CAMERA_MASK))
|
||||
{
|
||||
if (camera_st->data && camera_st->driver)
|
||||
{
|
||||
if (camera_st->cb.deinitialized)
|
||||
camera_st->cb.deinitialized();
|
||||
|
||||
if (camera_st->driver->free)
|
||||
camera_st->driver->free(camera_st->data);
|
||||
}
|
||||
|
||||
camera_st->data = NULL;
|
||||
}
|
||||
|
||||
if ((flags & DRIVER_BLUETOOTH_MASK))
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DEINIT, NULL);
|
||||
|
||||
if ((flags & DRIVER_WIFI_MASK))
|
||||
wifi_driver_ctl(RARCH_WIFI_CTL_DEINIT, NULL);
|
||||
|
||||
if (flags & DRIVER_LED)
|
||||
led_driver_free();
|
||||
|
||||
if (flags & DRIVERS_VIDEO_INPUT)
|
||||
{
|
||||
video_driver_free_internal();
|
||||
VIDEO_DRIVER_LOCK_FREE(video_st);
|
||||
video_st->data = NULL;
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
}
|
||||
|
||||
if (flags & DRIVER_AUDIO_MASK)
|
||||
audio_driver_deinit();
|
||||
|
||||
if ((flags & DRIVER_VIDEO_MASK))
|
||||
video_st->data = NULL;
|
||||
|
||||
if ((flags & DRIVER_INPUT_MASK))
|
||||
input_state_get_ptr()->current_data = NULL;
|
||||
|
||||
if ((flags & DRIVER_AUDIO_MASK))
|
||||
audio_state_get_ptr()->context_audio_data = NULL;
|
||||
|
||||
if (flags & DRIVER_MIDI_MASK)
|
||||
midi_driver_free();
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
cpu_scaling_driver_free();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void retroarch_deinit_drivers(struct retro_callbacks *cbs)
|
||||
{
|
||||
input_driver_state_t *input_st = input_state_get_ptr();
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
camera_driver_state_t *camera_st= camera_state_get_ptr();
|
||||
location_driver_state_t
|
||||
*location_st = location_state_get_ptr();
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* Tear down display widgets no matter what
|
||||
* in case the handle is lost in the threaded
|
||||
* video driver in the meantime
|
||||
* (breaking video_driver_has_widgets) */
|
||||
if (dispwidget_get_ptr()->inited)
|
||||
{
|
||||
gfx_widgets_deinit(
|
||||
dispwidget_get_ptr()->persisting);
|
||||
dispwidget_get_ptr()->active = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CRTSWITCHRES)
|
||||
/* Switchres deinit */
|
||||
if (video_st->crt_switching_active)
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
RARCH_LOG("[CRT]: Getting video info\n");
|
||||
RARCH_LOG("[CRT]: About to destroy SR\n");
|
||||
#endif
|
||||
crt_destroy_modes(&video_st->crt_switch_st);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Video */
|
||||
video_display_server_destroy();
|
||||
|
||||
video_st->use_rgba = false;
|
||||
video_st->hdr_support = false;
|
||||
video_st->active = false;
|
||||
video_st->cache_context = false;
|
||||
video_st->cache_context_ack = false;
|
||||
video_st->record_gpu_buffer = NULL;
|
||||
video_st->current_video = NULL;
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
|
||||
/* Audio */
|
||||
audio_state_get_ptr()->active = false;
|
||||
audio_state_get_ptr()->current_audio = NULL;
|
||||
|
||||
/* Input */
|
||||
input_st->keyboard_linefeed_enable = false;
|
||||
input_st->block_hotkey = false;
|
||||
input_st->block_libretro_input = false;
|
||||
|
||||
if (input_st)
|
||||
input_st->nonblocking_flag = false;
|
||||
|
||||
memset(&input_st->turbo_btns, 0, sizeof(turbo_buttons_t));
|
||||
memset(&input_st->analog_requested, 0,
|
||||
sizeof(input_st->analog_requested));
|
||||
input_st->current_driver = NULL;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
menu_driver_destroy(
|
||||
menu_state_get_ptr());
|
||||
#endif
|
||||
location_st->active = false;
|
||||
destroy_location();
|
||||
|
||||
/* Camera */
|
||||
camera_st->active = false;
|
||||
camera_st->driver = NULL;
|
||||
camera_st->data = NULL;
|
||||
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DESTROY, NULL);
|
||||
wifi_driver_ctl(RARCH_WIFI_CTL_DESTROY, NULL);
|
||||
|
||||
cbs->frame_cb = retro_frame_null;
|
||||
cbs->poll_cb = retro_input_poll_null;
|
||||
cbs->sample_cb = NULL;
|
||||
cbs->sample_batch_cb = NULL;
|
||||
cbs->state_cb = NULL;
|
||||
|
||||
runloop_st->current_core.inited = false;
|
||||
}
|
||||
|
||||
bool driver_ctl(enum driver_ctl_state state, void *data)
|
||||
{
|
||||
driver_ctx_info_t *drv = (driver_ctx_info_t*)data;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case RARCH_DRIVER_CTL_SET_REFRESH_RATE:
|
||||
{
|
||||
float *hz = (float*)data;
|
||||
audio_driver_state_t
|
||||
*audio_st = audio_state_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned
|
||||
audio_output_sample_rate = settings->uints.audio_output_sample_rate;
|
||||
bool vrr_runloop_enable = settings->bools.vrr_runloop_enable;
|
||||
float video_refresh_rate = settings->floats.video_refresh_rate;
|
||||
float audio_max_timing_skew = settings->floats.audio_max_timing_skew;
|
||||
bool video_adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned video_swap_interval = settings->uints.video_swap_interval;
|
||||
|
||||
video_monitor_set_refresh_rate(*hz);
|
||||
|
||||
/* Sets audio monitor rate to new value. */
|
||||
audio_st->source_ratio_original =
|
||||
audio_st->source_ratio_current =
|
||||
(double)audio_output_sample_rate / audio_st->input;
|
||||
|
||||
driver_adjust_system_rates(
|
||||
vrr_runloop_enable,
|
||||
video_refresh_rate,
|
||||
audio_max_timing_skew,
|
||||
video_adaptive_vsync,
|
||||
video_swap_interval
|
||||
);
|
||||
}
|
||||
break;
|
||||
case RARCH_DRIVER_CTL_FIND_FIRST:
|
||||
if (!drv)
|
||||
return false;
|
||||
find_driver_nonempty(drv->label, 0, drv->s, drv->len);
|
||||
break;
|
||||
case RARCH_DRIVER_CTL_FIND_LAST:
|
||||
if (!drv)
|
||||
return false;
|
||||
driver_find_last(drv->label, drv->s, drv->len);
|
||||
break;
|
||||
case RARCH_DRIVER_CTL_FIND_PREV:
|
||||
if (!drv)
|
||||
return false;
|
||||
return driver_find_prev(drv->label, drv->s, drv->len);
|
||||
case RARCH_DRIVER_CTL_FIND_NEXT:
|
||||
if (!drv)
|
||||
return false;
|
||||
return driver_find_next(drv->label, drv->s, drv->len);
|
||||
case RARCH_DRIVER_CTL_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* RUNAHEAD */
|
||||
|
||||
#ifdef HAVE_RUNAHEAD
|
||||
@ -14034,14 +13166,7 @@ void runloop_set_current_core_type(
|
||||
runloop_st->current_core_type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* retroarch_fail:
|
||||
* @error_code : Error code.
|
||||
* @error : Error message to show.
|
||||
*
|
||||
* Sanely kills the program.
|
||||
**/
|
||||
static void retroarch_fail(int error_code, const char *error)
|
||||
void retroarch_fail(int error_code, const char *error)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
/* We cannot longjmp unless we're in retroarch_main_init().
|
||||
@ -16020,9 +15145,6 @@ void rarch_favorites_deinit(void)
|
||||
/* Libretro core loader */
|
||||
|
||||
static void retro_run_null(void) { }
|
||||
static void retro_frame_null(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch) { }
|
||||
static void retro_input_poll_null(void) { }
|
||||
|
||||
static int16_t core_input_state_poll_late(unsigned port,
|
||||
unsigned device, unsigned idx, unsigned id)
|
||||
|
@ -182,6 +182,15 @@ typedef enum apple_view_type
|
||||
|
||||
bool retroarch_get_current_savestate_path(char *path, size_t len);
|
||||
|
||||
/**
|
||||
* retroarch_fail:
|
||||
* @error_code : Error code.
|
||||
* @error : Error message to show.
|
||||
*
|
||||
* Sanely kills the program.
|
||||
**/
|
||||
void retroarch_fail(int error_code, const char *error);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -114,6 +114,8 @@ void driver_wifi_tether_start_stop(bool start, char* configfile);
|
||||
|
||||
bool wifi_driver_ctl(enum rarch_wifi_ctl_state state, void *data);
|
||||
|
||||
extern const wifi_driver_t *wifi_drivers[];
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user