diff --git a/Makefile.common b/Makefile.common index 840324f852..1725c33ba6 100644 --- a/Makefile.common +++ b/Makefile.common @@ -234,6 +234,7 @@ endif OBJ += frontend/frontend_driver.o \ retroarch.o \ + driver.o \ camera/camera_driver.o \ record/record_driver.o \ command.o \ diff --git a/bluetooth/bluetooth_driver.h b/bluetooth/bluetooth_driver.h index 404dec082b..498bd23804 100644 --- a/bluetooth/bluetooth_driver.h +++ b/bluetooth/bluetooth_driver.h @@ -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 diff --git a/driver.c b/driver.c new file mode 100644 index 0000000000..8d9dddcf54 --- /dev/null +++ b/driver.c @@ -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 . + */ + +#include + +#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; +} diff --git a/driver.h b/driver.h index 0408de381f..fc454729c8 100644 --- a/driver.h +++ b/driver.h @@ -25,6 +25,7 @@ #include #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 diff --git a/griffin/griffin.c b/griffin/griffin.c index ac0f1a24e9..cf27d2bd5b 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -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" diff --git a/retroarch.c b/retroarch.c index 8ed880082f..e1275921cf 100644 --- a/retroarch.c +++ b/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) diff --git a/retroarch.h b/retroarch.h index b1388e5cec..3565806a84 100644 --- a/retroarch.h +++ b/retroarch.h @@ -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 diff --git a/wifi/wifi_driver.h b/wifi/wifi_driver.h index b32400cabb..cc71b11236 100644 --- a/wifi/wifi_driver.h +++ b/wifi/wifi_driver.h @@ -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