mirror of
https://github.com/libretro/RetroArch
synced 2025-02-19 12:41:00 +00:00
Combine driver.c into retroarch.c
This commit is contained in:
parent
ef0672f80b
commit
1ab6028b00
@ -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 \
|
||||
|
932
driver.c
932
driver.c
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "core_info.h"
|
||||
#include "driver.h"
|
||||
#include "retroarch.h"
|
||||
#include "runloop.h"
|
||||
#include "verbosity.h"
|
||||
|
||||
#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;
|
||||
}
|
2
driver.h
2
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
|
||||
|
@ -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"
|
||||
|
@ -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 = "<group>"; };
|
||||
05422E5C2140CFC500F09961 /* Metal.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Metal.xcconfig; sourceTree = "<group>"; };
|
||||
0548E2B220F976E10094A083 /* driver.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = driver.c; path = ../../driver.c; sourceTree = "<group>"; };
|
||||
0548E2B320F976E10094A083 /* dynamic.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dynamic.c; path = ../../dynamic.c; sourceTree = "<group>"; };
|
||||
0548E2B420F976E10094A083 /* dynamic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dynamic.h; path = ../../dynamic.h; sourceTree = "<group>"; };
|
||||
0548E2B520F976E20094A083 /* driver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = driver.h; path = ../../driver.h; sourceTree = "<group>"; };
|
||||
|
879
retroarch.c
879
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user