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