From 1ab6028b00ca8edc538c2e7a0b850bbc0c5531c3 Mon Sep 17 00:00:00 2001 From: libretroadmin Date: Mon, 9 Jan 2023 03:20:25 +0100 Subject: [PATCH] Combine driver.c into retroarch.c --- Makefile.common | 1 - driver.c | 932 ------------------ driver.h | 2 - griffin/griffin.c | 1 - .../RetroArch_Metal.xcodeproj/project.pbxproj | 1 - retroarch.c | 879 +++++++++++++++++ 6 files changed, 879 insertions(+), 937 deletions(-) delete mode 100644 driver.c diff --git a/Makefile.common b/Makefile.common index 817f0fb19b..8f315b3380 100644 --- a/Makefile.common +++ b/Makefile.common @@ -239,7 +239,6 @@ endif OBJ += frontend/frontend_driver.o \ retroarch.o \ runloop.o \ - driver.o \ ui/ui_companion_driver.o \ camera/camera_driver.o \ record/record_driver.o \ diff --git a/driver.c b/driver.c deleted file mode 100644 index 41560ca67b..0000000000 --- a/driver.c +++ /dev/null @@ -1,932 +0,0 @@ -/* 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" - -#ifdef HAVE_BLUETOOTH -#include "bluetooth/bluetooth_driver.h" -#endif -#ifdef HAVE_NETWORKING -#ifdef HAVE_WIFI -#include "network/wifi_driver.h" -#endif -#endif -#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" -#ifdef HAVE_CHEEVOS -#include "cheevos/cheevos_menu.h" -#endif -#endif - -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); - } - } -#ifdef HAVE_BLUETOOTH - 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]; - } - } -#endif -#ifdef HAVE_WIFI - 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]; - } - } -#endif - 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; - - /* Update video swap interval if automatic - * switching is enabled */ - runloop_set_video_swap_interval( - vrr_runloop_enable, - video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE, - video_swap_interval, - audio_max_timing_skew, - video_refresh_rate, - input_fps); - video_swap_interval = runloop_get_video_swap_interval( - video_swap_interval); - - 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->flags &= ~RUNLOOP_FLAG_FORCE_NONBLOCK; - - if (input_fps > 0.0) - { - float timing_skew_hz = video_refresh_rate; - - if (video_st->flags & VIDEO_FLAG_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, - video_swap_interval, - input_fps)) - { - /* We won't be able to do VSync reliably - when game FPS > monitor FPS. */ - runloop_st->flags |= RUNLOOP_FLAG_FORCE_NONBLOCK; - 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->flags & INP_FLAG_NONBLOCKING) : 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 = runloop_get_video_swap_interval( - settings->uints.video_swap_interval); - bool video_driver_active = video_st->flags & VIDEO_FLAG_ACTIVE; - bool audio_driver_active = audio_st->flags & AUDIO_FLAG_ACTIVE; - bool runloop_force_nonblock = runloop_st->flags & RUNLOOP_FLAG_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; - dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr(); - /* By default, we want display widgets to persist through driver reinits. */ - p_dispwidget->flags |= DISPGFX_WIDGET_FLAG_PERSISTING; -#endif -#ifdef HAVE_MENU - /* By default, we want the menu to persist through driver reinits. */ - if (menu_st) - menu_st->flags |= MENU_ST_FLAG_DATA_OWN; -#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->flags & VIDEO_FLAG_CACHE_CONTEXT_ACK) - && hwr->context_reset) - hwr->context_reset(); - video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT_ACK; - 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); - } - - /* Regular display refresh rate startup autoswitch based on content av_info */ - if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK)) - { - struct retro_system_av_info *av_info = &video_st->av_info; - float refresh_rate = av_info->timing.fps; - unsigned autoswitch_refresh_rate = settings->uints.video_autoswitch_refresh_rate; - bool exclusive_fullscreen = settings->bools.video_fullscreen && !settings->bools.video_windowed_fullscreen; - bool windowed_fullscreen = settings->bools.video_fullscreen && settings->bools.video_windowed_fullscreen; - bool all_fullscreen = settings->bools.video_fullscreen || settings->bools.video_windowed_fullscreen; - - if ( refresh_rate > 0.0 - && !settings->uints.crt_switch_resolution - && !settings->bools.vrr_runloop_enable - && video_display_server_has_resolution_list() - && (autoswitch_refresh_rate != AUTOSWITCH_REFRESH_RATE_OFF) - && (fabs(settings->floats.video_refresh_rate - refresh_rate) > 1)) - { - if (((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_EXCLUSIVE_FULLSCREEN) && exclusive_fullscreen) || - ((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_WINDOWED_FULLSCREEN) && windowed_fullscreen) || - ((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_ALL_FULLSCREEN) && all_fullscreen)) - { - bool video_switch_refresh_rate = false; - - video_switch_refresh_rate_maybe(&refresh_rate, &video_switch_refresh_rate); - - if (video_switch_refresh_rate && video_display_server_set_refresh_rate(refresh_rate)) - { - int reinit_flags = DRIVER_AUDIO_MASK; - video_monitor_set_refresh_rate(refresh_rate); - /* Audio must reinit after successful rate switch */ - command_event(CMD_EVENT_REINIT, &reinit_flags); - } - } - } - } - - 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(); - } - } - } - } - -#ifdef HAVE_BLUETOOTH - if (flags & DRIVER_BLUETOOTH_MASK) - bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_INIT, NULL); -#endif -#ifdef HAVE_WIFI - if ((flags & DRIVER_WIFI_MASK)) - wifi_driver_ctl(RARCH_WIFI_CTL_INIT, NULL); -#endif - - 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->flags & - VIDEO_FLAG_FORCE_FULLSCREEN; - bool video_is_fullscreen = settings->bools.video_fullscreen || - rarch_force_fullscreen; - - p_dispwidget->active= gfx_widgets_init( - p_disp, - anim_get_ptr(), - settings, - (uintptr_t)&p_dispwidget->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 - menu_contentless_cores_context_init(); - } - } - - /* 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->flags & INP_FLAG_NONBLOCKING)) - 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); - -#ifndef HAVE_LAKKA_SWITCH -#ifdef HAVE_LAKKA - cpu_scaling_driver_init(); -#endif -#endif /* #ifndef HAVE_LAKKA_SWITCH */ -} - -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(); -#if defined(HAVE_GFX_WIDGETS) - dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr(); -#endif - - 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 (p_dispwidget->flags & DISPGFX_WIDGET_FLAG_INITED) - { - gfx_widgets_deinit(p_dispwidget->flags & DISPGFX_WIDGET_FLAG_PERSISTING); - p_dispwidget->active = false; - } -#endif - -#ifdef HAVE_MENU - if (flags & DRIVER_MENU_MASK) - { -#ifdef HAVE_LIBRETRODB - menu_explore_context_deinit(); -#endif - menu_contentless_cores_context_deinit(); - -#ifdef HAVE_CHEEVOS - rcheevos_menu_reset_badges(); -#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; - } - -#ifdef HAVE_BLUETOOTH - if ((flags & DRIVER_BLUETOOTH_MASK)) - bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DEINIT, NULL); -#endif -#ifdef HAVE_WIFI - if ((flags & DRIVER_WIFI_MASK)) - wifi_driver_ctl(RARCH_WIFI_CTL_DEINIT, NULL); -#endif - - 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(); - -#ifndef HAVE_LAKKA_SWITCH -#ifdef HAVE_LAKKA - cpu_scaling_driver_free(); -#endif -#endif /* #ifndef HAVE_LAKKA_SWITCH */ -} - -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) */ - dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr(); - if (p_dispwidget->flags & DISPGFX_WIDGET_FLAG_INITED) - { - gfx_widgets_deinit( - p_dispwidget->flags & DISPGFX_WIDGET_FLAG_PERSISTING); - p_dispwidget->active = false; - } -#endif - -#if defined(HAVE_CRTSWITCHRES) - /* Switchres deinit */ - if (video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE) - crt_destroy_modes(&video_st->crt_switch_st); -#endif - - /* Video */ - video_display_server_destroy(); - - video_st->flags &= ~(VIDEO_FLAG_ACTIVE | VIDEO_FLAG_USE_RGBA | - VIDEO_FLAG_HDR_SUPPORT | VIDEO_FLAG_CACHE_CONTEXT | - VIDEO_FLAG_CACHE_CONTEXT_ACK - ); - video_st->record_gpu_buffer = NULL; - video_st->current_video = NULL; - video_driver_set_cached_frame_ptr(NULL); - - /* Audio */ - audio_state_get_ptr()->flags &= ~AUDIO_FLAG_ACTIVE; - audio_state_get_ptr()->current_audio = NULL; - - if (input_st) - { - /* Input */ - input_st->flags &= ~(INP_FLAG_KB_LINEFEED_ENABLE - | INP_FLAG_BLOCK_HOTKEY - | INP_FLAG_BLOCK_LIBRETRO_INPUT - | INP_FLAG_NONBLOCKING); - - 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; - -#ifdef HAVE_BLUETOOTH - bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DESTROY, NULL); -#endif -#ifdef HAVE_WIFI - wifi_driver_ctl(RARCH_WIFI_CTL_DESTROY, NULL); -#endif - - 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.flags &= ~RETRO_CORE_FLAG_INITED; -} - -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 fc454729c8..8eef1776a7 100644 --- a/driver.h +++ b/driver.h @@ -133,8 +133,6 @@ 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 3d0525f505..c2de253044 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1237,7 +1237,6 @@ RETROARCH #include "../retroarch.c" #include "../runloop.c" #include "../command.c" -#include "../driver.c" #include "../midi_driver.c" #include "../location_driver.c" #include "../ui/ui_companion_driver.c" diff --git a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj index e24e3248e2..7fc4f527e0 100644 --- a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj @@ -149,7 +149,6 @@ 05422E592140C8DB00F09961 /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 05422E5B2140CE3500F09961 /* VulkanConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = VulkanConfig.xcconfig; sourceTree = ""; }; 05422E5C2140CFC500F09961 /* Metal.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Metal.xcconfig; sourceTree = ""; }; - 0548E2B220F976E10094A083 /* driver.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = driver.c; path = ../../driver.c; sourceTree = ""; }; 0548E2B320F976E10094A083 /* dynamic.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dynamic.c; path = ../../dynamic.c; sourceTree = ""; }; 0548E2B420F976E10094A083 /* dynamic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dynamic.h; path = ../../dynamic.h; sourceTree = ""; }; 0548E2B520F976E20094A083 /* driver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = driver.h; path = ../../driver.h; sourceTree = ""; }; diff --git a/retroarch.c b/retroarch.c index bb6b9c932a..806a7445da 100644 --- a/retroarch.c +++ b/retroarch.c @@ -179,11 +179,13 @@ #include "ui/ui_companion_driver.h" #include "verbosity.h" +#include "gfx/video_driver.h" #include "gfx/video_display_server.h" #ifdef HAVE_BLUETOOTH #include "bluetooth/bluetooth_driver.h" #endif #include "misc/cpufreq/cpufreq.h" +#include "led/led_driver.h" #include "midi_driver.h" #include "core.h" #include "configuration.h" @@ -332,6 +334,883 @@ static const void *MAGIC_POINTER = (void*)(uintptr_t)0x0DEFACED; static access_state_t access_state_st = {0}; static struct global global_driver_st = {0}; /* retro_time_t alignment */ +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); + } + } +#ifdef HAVE_BLUETOOTH + 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]; + } + } +#endif +#ifdef HAVE_WIFI + 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]; + } + } +#endif + 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; + + /* Update video swap interval if automatic + * switching is enabled */ + runloop_set_video_swap_interval( + vrr_runloop_enable, + video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE, + video_swap_interval, + audio_max_timing_skew, + video_refresh_rate, + input_fps); + video_swap_interval = runloop_get_video_swap_interval( + video_swap_interval); + + 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->flags &= ~RUNLOOP_FLAG_FORCE_NONBLOCK; + + if (input_fps > 0.0) + { + float timing_skew_hz = video_refresh_rate; + + if (video_st->flags & VIDEO_FLAG_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, + video_swap_interval, + input_fps)) + { + /* We won't be able to do VSync reliably + when game FPS > monitor FPS. */ + runloop_st->flags |= RUNLOOP_FLAG_FORCE_NONBLOCK; + 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->flags & INP_FLAG_NONBLOCKING) : 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 = runloop_get_video_swap_interval( + settings->uints.video_swap_interval); + bool video_driver_active = video_st->flags & VIDEO_FLAG_ACTIVE; + bool audio_driver_active = audio_st->flags & AUDIO_FLAG_ACTIVE; + bool runloop_force_nonblock = runloop_st->flags & RUNLOOP_FLAG_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; + dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr(); + /* By default, we want display widgets to persist through driver reinits. */ + p_dispwidget->flags |= DISPGFX_WIDGET_FLAG_PERSISTING; +#endif +#ifdef HAVE_MENU + /* By default, we want the menu to persist through driver reinits. */ + if (menu_st) + menu_st->flags |= MENU_ST_FLAG_DATA_OWN; +#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->flags & VIDEO_FLAG_CACHE_CONTEXT_ACK) + && hwr->context_reset) + hwr->context_reset(); + video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT_ACK; + 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); + } + + /* Regular display refresh rate startup autoswitch based on content av_info */ + if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK)) + { + struct retro_system_av_info *av_info = &video_st->av_info; + float refresh_rate = av_info->timing.fps; + unsigned autoswitch_refresh_rate = settings->uints.video_autoswitch_refresh_rate; + bool exclusive_fullscreen = settings->bools.video_fullscreen && !settings->bools.video_windowed_fullscreen; + bool windowed_fullscreen = settings->bools.video_fullscreen && settings->bools.video_windowed_fullscreen; + bool all_fullscreen = settings->bools.video_fullscreen || settings->bools.video_windowed_fullscreen; + + if ( refresh_rate > 0.0 + && !settings->uints.crt_switch_resolution + && !settings->bools.vrr_runloop_enable + && video_display_server_has_resolution_list() + && (autoswitch_refresh_rate != AUTOSWITCH_REFRESH_RATE_OFF) + && (fabs(settings->floats.video_refresh_rate - refresh_rate) > 1)) + { + if (((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_EXCLUSIVE_FULLSCREEN) && exclusive_fullscreen) || + ((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_WINDOWED_FULLSCREEN) && windowed_fullscreen) || + ((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_ALL_FULLSCREEN) && all_fullscreen)) + { + bool video_switch_refresh_rate = false; + + video_switch_refresh_rate_maybe(&refresh_rate, &video_switch_refresh_rate); + + if (video_switch_refresh_rate && video_display_server_set_refresh_rate(refresh_rate)) + { + int reinit_flags = DRIVER_AUDIO_MASK; + video_monitor_set_refresh_rate(refresh_rate); + /* Audio must reinit after successful rate switch */ + command_event(CMD_EVENT_REINIT, &reinit_flags); + } + } + } + } + + 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(); + } + } + } + } + +#ifdef HAVE_BLUETOOTH + if (flags & DRIVER_BLUETOOTH_MASK) + bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_INIT, NULL); +#endif +#ifdef HAVE_WIFI + if ((flags & DRIVER_WIFI_MASK)) + wifi_driver_ctl(RARCH_WIFI_CTL_INIT, NULL); +#endif + + 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->flags & + VIDEO_FLAG_FORCE_FULLSCREEN; + bool video_is_fullscreen = settings->bools.video_fullscreen || + rarch_force_fullscreen; + + p_dispwidget->active= gfx_widgets_init( + p_disp, + anim_get_ptr(), + settings, + (uintptr_t)&p_dispwidget->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 + menu_contentless_cores_context_init(); + } + } + + /* 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->flags & INP_FLAG_NONBLOCKING)) + 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); + +#ifndef HAVE_LAKKA_SWITCH +#ifdef HAVE_LAKKA + cpu_scaling_driver_init(); +#endif +#endif /* #ifndef HAVE_LAKKA_SWITCH */ +} + +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(); +#if defined(HAVE_GFX_WIDGETS) + dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr(); +#endif + + 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 (p_dispwidget->flags & DISPGFX_WIDGET_FLAG_INITED) + { + gfx_widgets_deinit(p_dispwidget->flags & DISPGFX_WIDGET_FLAG_PERSISTING); + p_dispwidget->active = false; + } +#endif + +#ifdef HAVE_MENU + if (flags & DRIVER_MENU_MASK) + { +#ifdef HAVE_LIBRETRODB + menu_explore_context_deinit(); +#endif + menu_contentless_cores_context_deinit(); + +#ifdef HAVE_CHEEVOS + rcheevos_menu_reset_badges(); +#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; + } + +#ifdef HAVE_BLUETOOTH + if ((flags & DRIVER_BLUETOOTH_MASK)) + bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DEINIT, NULL); +#endif +#ifdef HAVE_WIFI + if ((flags & DRIVER_WIFI_MASK)) + wifi_driver_ctl(RARCH_WIFI_CTL_DEINIT, NULL); +#endif + + 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(); + +#ifndef HAVE_LAKKA_SWITCH +#ifdef HAVE_LAKKA + cpu_scaling_driver_free(); +#endif +#endif /* #ifndef HAVE_LAKKA_SWITCH */ +} + +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_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) */ + dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr(); + if (p_dispwidget->flags & DISPGFX_WIDGET_FLAG_INITED) + { + gfx_widgets_deinit( + p_dispwidget->flags & DISPGFX_WIDGET_FLAG_PERSISTING); + p_dispwidget->active = false; + } +#endif + +#if defined(HAVE_CRTSWITCHRES) + /* Switchres deinit */ + if (video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE) + crt_destroy_modes(&video_st->crt_switch_st); +#endif + + /* Video */ + video_display_server_destroy(); + + video_st->flags &= ~(VIDEO_FLAG_ACTIVE | VIDEO_FLAG_USE_RGBA | + VIDEO_FLAG_HDR_SUPPORT | VIDEO_FLAG_CACHE_CONTEXT | + VIDEO_FLAG_CACHE_CONTEXT_ACK + ); + video_st->record_gpu_buffer = NULL; + video_st->current_video = NULL; + video_driver_set_cached_frame_ptr(NULL); + + /* Audio */ + audio_state_get_ptr()->flags &= ~AUDIO_FLAG_ACTIVE; + audio_state_get_ptr()->current_audio = NULL; + + if (input_st) + { + /* Input */ + input_st->flags &= ~(INP_FLAG_KB_LINEFEED_ENABLE + | INP_FLAG_BLOCK_HOTKEY + | INP_FLAG_BLOCK_LIBRETRO_INPUT + | INP_FLAG_NONBLOCKING); + + 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; + +#ifdef HAVE_BLUETOOTH + bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DESTROY, NULL); +#endif +#ifdef HAVE_WIFI + wifi_driver_ctl(RARCH_WIFI_CTL_DESTROY, NULL); +#endif + + 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.flags &= ~RETRO_CORE_FLAG_INITED; +} + +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; +} + access_state_t *access_state_get_ptr(void) { return &access_state_st;