mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Move code from retroarch.c to video_driver.c
This commit is contained in:
parent
e4ccc2508e
commit
c17bcb8d91
@ -23,6 +23,10 @@
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <gfx/video_frame.h>
|
||||
|
||||
#include "../config.def.h"
|
||||
|
||||
#include "video_driver.h"
|
||||
#include "video_filter.h"
|
||||
#include "video_display_server.h"
|
||||
@ -39,6 +43,7 @@
|
||||
#include "../menu/menu_driver.h"
|
||||
#endif
|
||||
|
||||
#include "../audio/audio_driver.h"
|
||||
#include "../frontend/frontend_driver.h"
|
||||
#include "../ui/ui_companion_driver.h"
|
||||
#include "../driver.h"
|
||||
@ -47,6 +52,8 @@
|
||||
#include "../retroarch.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
#define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time)))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct string_list *list;
|
||||
@ -3148,3 +3155,757 @@ const char* video_driver_get_gpu_api_version_string(void)
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
return video_st->gpu_api_version_string;
|
||||
}
|
||||
|
||||
bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
{
|
||||
video_info_t video;
|
||||
unsigned max_dim, scale, width, height;
|
||||
video_viewport_t *custom_vp = NULL;
|
||||
input_driver_t *tmp = NULL;
|
||||
static uint16_t dummy_pixels[32] = {0};
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
input_driver_state_t *input_st = input_state_get_ptr();
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
struct retro_game_geometry *geom = &video_st->av_info.geometry;
|
||||
const enum retro_pixel_format
|
||||
video_driver_pix_fmt = video_st->pix_fmt;
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
const char *path_softfilter_plugin = settings->paths.path_softfilter_plugin;
|
||||
|
||||
if (!string_is_empty(path_softfilter_plugin))
|
||||
video_driver_init_filter(video_driver_pix_fmt, settings);
|
||||
#endif
|
||||
|
||||
max_dim = MAX(geom->max_width, geom->max_height);
|
||||
scale = next_pow2(max_dim) / RARCH_SCALE_BASE;
|
||||
scale = MAX(scale, 1);
|
||||
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
if (video_st->state_filter)
|
||||
scale = video_st->state_scale;
|
||||
#endif
|
||||
|
||||
/* Update core-dependent aspect ratio values. */
|
||||
video_driver_set_viewport_square_pixel(geom);
|
||||
video_driver_set_viewport_core();
|
||||
video_driver_set_viewport_config(geom,
|
||||
settings->floats.video_aspect_ratio,
|
||||
settings->bools.video_aspect_ratio_auto);
|
||||
|
||||
/* Update CUSTOM viewport. */
|
||||
custom_vp = &settings->video_viewport_custom;
|
||||
|
||||
if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
|
||||
{
|
||||
float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
|
||||
aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
|
||||
(custom_vp->width && custom_vp->height) ?
|
||||
(float)custom_vp->width / custom_vp->height : default_aspect;
|
||||
}
|
||||
|
||||
{
|
||||
/* Guard against aspect ratio index possibly being out of bounds */
|
||||
unsigned new_aspect_idx = settings->uints.video_aspect_ratio_idx;
|
||||
if (new_aspect_idx > ASPECT_RATIO_END)
|
||||
new_aspect_idx = settings->uints.video_aspect_ratio_idx = 0;
|
||||
|
||||
video_driver_set_aspect_ratio_value(
|
||||
aspectratio_lut[new_aspect_idx].value);
|
||||
}
|
||||
|
||||
if (settings->bools.video_fullscreen || video_st->force_fullscreen)
|
||||
{
|
||||
width = settings->uints.video_fullscreen_x;
|
||||
height = settings->uints.video_fullscreen_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
if (is_running_on_xbox())
|
||||
{
|
||||
width = settings->uints.video_fullscreen_x != 0 ? settings->uints.video_fullscreen_x : 3840;
|
||||
height = settings->uints.video_fullscreen_y != 0 ? settings->uints.video_fullscreen_y : 2160;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
|
||||
bool window_custom_size_enable = settings->bools.video_window_save_positions;
|
||||
#else
|
||||
bool window_custom_size_enable = settings->bools.video_window_custom_size_enable;
|
||||
#endif
|
||||
/* TODO: remove when the new window resizing core is hooked */
|
||||
if (window_custom_size_enable &&
|
||||
settings->uints.window_position_width &&
|
||||
settings->uints.window_position_height)
|
||||
{
|
||||
width = settings->uints.window_position_width;
|
||||
height = settings->uints.window_position_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
float video_scale = settings->floats.video_scale;
|
||||
/* Determine maximum allowed window dimensions
|
||||
* NOTE: We cannot read the actual display
|
||||
* metrics here, because the context driver
|
||||
* has not yet been initialised... */
|
||||
|
||||
/* > Try explicitly configured values */
|
||||
unsigned max_win_width = settings->uints.window_auto_width_max;
|
||||
unsigned max_win_height = settings->uints.window_auto_height_max;
|
||||
|
||||
/* > Handle invalid settings */
|
||||
if ((max_win_width == 0) || (max_win_height == 0))
|
||||
{
|
||||
/* > Try configured fullscreen width/height */
|
||||
max_win_width = settings->uints.video_fullscreen_x;
|
||||
max_win_height = settings->uints.video_fullscreen_y;
|
||||
|
||||
if ((max_win_width == 0) || (max_win_height == 0))
|
||||
{
|
||||
/* Maximum window width/size *must* be non-zero;
|
||||
* if all else fails, used defined default
|
||||
* maximum window size */
|
||||
max_win_width = DEFAULT_WINDOW_AUTO_WIDTH_MAX;
|
||||
max_win_height = DEFAULT_WINDOW_AUTO_HEIGHT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine nominal window size based on
|
||||
* core geometry */
|
||||
if (settings->bools.video_force_aspect)
|
||||
{
|
||||
/* Do rounding here to simplify integer
|
||||
* scale correctness. */
|
||||
unsigned base_width = roundf(geom->base_height *
|
||||
video_st->aspect_ratio);
|
||||
width = roundf(base_width * video_scale);
|
||||
}
|
||||
else
|
||||
width = roundf(geom->base_width * video_scale);
|
||||
|
||||
height = roundf(geom->base_height * video_scale);
|
||||
|
||||
/* Cap window size to maximum allowed values */
|
||||
if ((width > max_win_width) || (height > max_win_height))
|
||||
{
|
||||
unsigned geom_width = (width > 0) ? width : 1;
|
||||
unsigned geom_height = (height > 0) ? height : 1;
|
||||
float geom_aspect = (float)geom_width / (float)geom_height;
|
||||
float max_win_aspect = (float)max_win_width / (float)max_win_height;
|
||||
|
||||
if (geom_aspect > max_win_aspect)
|
||||
{
|
||||
width = max_win_width;
|
||||
height = geom_height * max_win_width / geom_width;
|
||||
/* Account for any possible rounding errors... */
|
||||
height = (height < 1) ? 1 : height;
|
||||
height = (height > max_win_height) ? max_win_height : height;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = max_win_height;
|
||||
width = geom_width * max_win_height / geom_height;
|
||||
/* Account for any possible rounding errors... */
|
||||
width = (width < 1) ? 1 : width;
|
||||
width = (width > max_win_width) ? max_win_width : width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (width && height)
|
||||
RARCH_LOG("[Video]: Video @ %ux%u\n", width, height);
|
||||
else
|
||||
RARCH_LOG("[Video]: Video @ fullscreen\n");
|
||||
|
||||
video_st->display_type = RARCH_DISPLAY_NONE;
|
||||
video_st->display = 0;
|
||||
video_st->display_userdata = 0;
|
||||
video_st->window = 0;
|
||||
|
||||
video_st->scaler_ptr = video_driver_pixel_converter_init(
|
||||
video_st->pix_fmt,
|
||||
VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st),
|
||||
RARCH_SCALE_BASE * scale);
|
||||
|
||||
video.width = width;
|
||||
video.height = height;
|
||||
video.fullscreen = settings->bools.video_fullscreen ||
|
||||
video_st->force_fullscreen;
|
||||
video.vsync = settings->bools.video_vsync &&
|
||||
!runloop_st->force_nonblock;
|
||||
video.force_aspect = settings->bools.video_force_aspect;
|
||||
video.font_enable = settings->bools.video_font_enable;
|
||||
video.swap_interval = settings->uints.video_swap_interval;
|
||||
video.adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
#ifdef GEKKO
|
||||
video.viwidth = settings->uints.video_viwidth;
|
||||
video.vfilter = settings->bools.video_vfilter;
|
||||
#endif
|
||||
video.smooth = settings->bools.video_smooth;
|
||||
video.ctx_scaling = settings->bools.video_ctx_scaling;
|
||||
video.input_scale = scale;
|
||||
video.font_size = settings->floats.video_font_size;
|
||||
video.path_font = settings->paths.path_font;
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
video.rgb32 =
|
||||
video_st->state_filter
|
||||
? video_st->state_out_rgb32
|
||||
: (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
#else
|
||||
video.rgb32 =
|
||||
(video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
#endif
|
||||
video.parent = 0;
|
||||
|
||||
video_st->started_fullscreen = video.fullscreen;
|
||||
/* Reset video frame count */
|
||||
video_st->frame_count = 0;
|
||||
|
||||
tmp = input_state_get_ptr()->current_driver;
|
||||
/* Need to grab the "real" video driver interface on a reinit. */
|
||||
video_driver_find_driver(settings,
|
||||
"video driver", verbosity_enabled);
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
video.is_threaded =
|
||||
VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
*video_is_threaded = video.is_threaded;
|
||||
|
||||
if (video.is_threaded)
|
||||
{
|
||||
bool ret;
|
||||
/* Can't do hardware rendering with threaded driver currently. */
|
||||
RARCH_LOG("[Video]: Starting threaded video driver ...\n");
|
||||
|
||||
ret = video_init_thread(
|
||||
(const video_driver_t**)&video_st->current_video,
|
||||
&video_st->data,
|
||||
&input_state_get_ptr()->current_driver,
|
||||
(void**)&input_state_get_ptr()->current_data,
|
||||
video_st->current_video,
|
||||
video);
|
||||
if (!ret)
|
||||
{
|
||||
RARCH_ERR("[Video]: Cannot open threaded video driver ... Exiting ...\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
video_st->data = video_st->current_video->init(
|
||||
&video,
|
||||
&input_state_get_ptr()->current_driver,
|
||||
(void**)&input_state_get_ptr()->current_data);
|
||||
|
||||
if (!video_st->data)
|
||||
{
|
||||
RARCH_ERR("[Video]: Cannot open video driver ... Exiting ...\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
video_st->poke = NULL;
|
||||
if (video_st->current_video->poke_interface)
|
||||
video_st->current_video->poke_interface(
|
||||
video_st->data, &video_st->poke);
|
||||
|
||||
if (video_st->current_video->viewport_info &&
|
||||
(!custom_vp->width ||
|
||||
!custom_vp->height))
|
||||
{
|
||||
/* Force custom viewport to have sane parameters. */
|
||||
custom_vp->width = width;
|
||||
custom_vp->height = height;
|
||||
|
||||
video_driver_get_viewport_info(custom_vp);
|
||||
}
|
||||
|
||||
video_driver_set_rotation(retroarch_get_rotation() % 4);
|
||||
|
||||
video_st->current_video->suppress_screensaver(video_st->data,
|
||||
settings->bools.ui_suspend_screensaver_enable);
|
||||
|
||||
if (!video_driver_init_input(tmp, settings, verbosity_enabled))
|
||||
return false;
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
input_overlay_deinit();
|
||||
input_overlay_init();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
if (settings->bools.video_layout_enable)
|
||||
{
|
||||
video_layout_init(video_st->data,
|
||||
video_driver_layout_render_interface());
|
||||
video_layout_load(settings->paths.path_video_layout);
|
||||
video_layout_view_select(settings->uints.video_layout_selected_view);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!runloop_st->current_core.game_loaded)
|
||||
video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8);
|
||||
|
||||
#if defined(PSP)
|
||||
video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f);
|
||||
#endif
|
||||
|
||||
video_context_driver_reset();
|
||||
|
||||
video_display_server_init(video_st->display_type);
|
||||
|
||||
if ((enum rotation)settings->uints.screen_orientation != ORIENTATION_NORMAL)
|
||||
video_display_server_set_screen_orientation((enum rotation)settings->uints.screen_orientation);
|
||||
|
||||
/* Ensure that we preserve the 'grab mouse'
|
||||
* state if it was enabled prior to driver
|
||||
* (re-)initialisation */
|
||||
if (input_st->grab_mouse_state)
|
||||
{
|
||||
video_driver_hide_mouse();
|
||||
if (input_driver_grab_mouse())
|
||||
input_st->grab_mouse_state = true;
|
||||
}
|
||||
else if (video.fullscreen)
|
||||
{
|
||||
video_driver_hide_mouse();
|
||||
if (!settings->bools.video_windowed_fullscreen)
|
||||
if (input_driver_grab_mouse())
|
||||
input_st->grab_mouse_state = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void video_driver_frame(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch)
|
||||
{
|
||||
char status_text[128];
|
||||
static char video_driver_msg[256];
|
||||
static retro_time_t curr_time;
|
||||
static retro_time_t fps_time;
|
||||
static float last_fps, frame_time;
|
||||
static uint64_t last_used_memory, last_total_memory;
|
||||
retro_time_t new_time;
|
||||
video_frame_info_t video_info;
|
||||
video_driver_state_t *video_st= &video_driver_st;
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
const enum retro_pixel_format
|
||||
video_driver_pix_fmt = video_st->pix_fmt;
|
||||
bool runloop_idle = runloop_st->idle;
|
||||
bool video_driver_active = video_st->active;
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
bool widgets_active = dispwidget_get_ptr()->active;
|
||||
#endif
|
||||
recording_state_t
|
||||
*recording_st = recording_state_get_ptr();
|
||||
|
||||
status_text[0] = '\0';
|
||||
video_driver_msg[0] = '\0';
|
||||
|
||||
if (!video_driver_active)
|
||||
return;
|
||||
|
||||
new_time = cpu_features_get_time_usec();
|
||||
|
||||
if (data)
|
||||
video_st->frame_cache_data = data;
|
||||
video_st->frame_cache_width = width;
|
||||
video_st->frame_cache_height = height;
|
||||
video_st->frame_cache_pitch = pitch;
|
||||
|
||||
if (
|
||||
video_st->scaler_ptr
|
||||
&& data
|
||||
&& (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555)
|
||||
&& (data != RETRO_HW_FRAME_BUFFER_VALID)
|
||||
&& video_pixel_frame_scale(
|
||||
video_st->scaler_ptr->scaler,
|
||||
video_st->scaler_ptr->scaler_out,
|
||||
data, width, height, pitch)
|
||||
)
|
||||
{
|
||||
data = video_st->scaler_ptr->scaler_out;
|
||||
pitch = video_st->scaler_ptr->scaler->out_stride;
|
||||
}
|
||||
|
||||
video_driver_build_info(&video_info);
|
||||
|
||||
/* Get the amount of frames per seconds. */
|
||||
if (video_st->frame_count)
|
||||
{
|
||||
unsigned fps_update_interval =
|
||||
video_info.fps_update_interval;
|
||||
unsigned memory_update_interval =
|
||||
video_info.memory_update_interval;
|
||||
size_t buf_pos = 1;
|
||||
/* set this to 1 to avoid an offset issue */
|
||||
unsigned write_index =
|
||||
video_st->frame_time_count++ &
|
||||
(MEASURE_FRAME_TIME_SAMPLES_COUNT - 1);
|
||||
frame_time = new_time - fps_time;
|
||||
video_st->frame_time_samples
|
||||
[write_index] = frame_time;
|
||||
fps_time = new_time;
|
||||
|
||||
if (video_info.fps_show)
|
||||
buf_pos = snprintf(
|
||||
status_text, sizeof(status_text),
|
||||
"FPS: %6.2f", last_fps);
|
||||
|
||||
if (video_info.framecount_show)
|
||||
{
|
||||
char frames_text[64];
|
||||
if (status_text[buf_pos-1] != '\0')
|
||||
strlcat(status_text, " || ", sizeof(status_text));
|
||||
snprintf(frames_text,
|
||||
sizeof(frames_text),
|
||||
"%s: %" PRIu64, msg_hash_to_str(MSG_FRAMES),
|
||||
(uint64_t)video_st->frame_count);
|
||||
buf_pos = strlcat(status_text, frames_text, sizeof(status_text));
|
||||
}
|
||||
|
||||
if (video_info.memory_show)
|
||||
{
|
||||
char mem[128];
|
||||
|
||||
if ((video_st->frame_count % memory_update_interval) == 0)
|
||||
{
|
||||
last_total_memory = frontend_driver_get_total_memory();
|
||||
last_used_memory = last_total_memory - frontend_driver_get_free_memory();
|
||||
}
|
||||
|
||||
mem[0] = '\0';
|
||||
snprintf(
|
||||
mem, sizeof(mem), "MEM: %.2f/%.2fMB", last_used_memory / (1024.0f * 1024.0f),
|
||||
last_total_memory / (1024.0f * 1024.0f));
|
||||
if (status_text[buf_pos-1] != '\0')
|
||||
strlcat(status_text, " || ", sizeof(status_text));
|
||||
strlcat(status_text, mem, sizeof(status_text));
|
||||
}
|
||||
|
||||
if ((video_st->frame_count % fps_update_interval) == 0)
|
||||
{
|
||||
last_fps = TIME_TO_FPS(curr_time, new_time,
|
||||
fps_update_interval);
|
||||
|
||||
strlcpy(video_st->window_title,
|
||||
video_st->title_buf,
|
||||
sizeof(video_st->window_title));
|
||||
|
||||
if (!string_is_empty(status_text))
|
||||
{
|
||||
strlcat(video_st->window_title,
|
||||
" || ", sizeof(video_st->window_title));
|
||||
strlcat(video_st->window_title,
|
||||
status_text, sizeof(video_st->window_title));
|
||||
}
|
||||
|
||||
curr_time = new_time;
|
||||
video_st->window_title_update = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_time = fps_time = new_time;
|
||||
|
||||
strlcpy(video_st->window_title,
|
||||
video_st->title_buf,
|
||||
sizeof(video_st->window_title));
|
||||
|
||||
if (video_info.fps_show)
|
||||
strlcpy(status_text,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
|
||||
sizeof(status_text));
|
||||
|
||||
video_st->window_title_update = true;
|
||||
}
|
||||
|
||||
/* Add core status message to status text */
|
||||
if (video_info.core_status_msg_show)
|
||||
{
|
||||
/* Note: We need to lock a mutex here. Strictly
|
||||
* speaking, runloop_core_status_msg is not part
|
||||
* of the message queue, but:
|
||||
* - It may be implemented as a queue in the future
|
||||
* - It seems unnecessary to create a new slock_t
|
||||
* object for this type of message when
|
||||
* _runloop_msg_queue_lock is already available
|
||||
* We therefore just call runloop_msg_queue_lock()/
|
||||
* runloop_msg_queue_unlock() in this case */
|
||||
RUNLOOP_MSG_QUEUE_LOCK(runloop_st);
|
||||
|
||||
/* Check whether duration timer has elapsed */
|
||||
runloop_st->core_status_msg.duration -= anim_get_ptr()->delta_time;
|
||||
|
||||
if (runloop_st->core_status_msg.duration < 0.0f)
|
||||
{
|
||||
runloop_st->core_status_msg.str[0] = '\0';
|
||||
runloop_st->core_status_msg.priority = 0;
|
||||
runloop_st->core_status_msg.duration = 0.0f;
|
||||
runloop_st->core_status_msg.set = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If status text is already set, add status
|
||||
* message at the end */
|
||||
if (!string_is_empty(status_text))
|
||||
{
|
||||
strlcat(status_text,
|
||||
" || ", sizeof(status_text));
|
||||
strlcat(status_text,
|
||||
runloop_st->core_status_msg.str,
|
||||
sizeof(status_text));
|
||||
}
|
||||
else
|
||||
strlcpy(status_text,
|
||||
runloop_st->core_status_msg.str,
|
||||
sizeof(status_text));
|
||||
}
|
||||
|
||||
RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st);
|
||||
}
|
||||
|
||||
/* Slightly messy code,
|
||||
* but we really need to do processing before blocking on VSync
|
||||
* for best possible scheduling.
|
||||
*/
|
||||
if (
|
||||
(
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
!video_st->state_filter ||
|
||||
#endif
|
||||
!video_info.post_filter_record
|
||||
|| !data
|
||||
|| video_st->record_gpu_buffer
|
||||
) && recording_st->data
|
||||
&& recording_st->driver
|
||||
&& recording_st->driver->push_video)
|
||||
recording_dump_frame(
|
||||
data, width, height,
|
||||
pitch, runloop_idle);
|
||||
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
if (data && video_st->state_filter)
|
||||
{
|
||||
unsigned output_width = 0;
|
||||
unsigned output_height = 0;
|
||||
unsigned output_pitch = 0;
|
||||
|
||||
rarch_softfilter_get_output_size(video_st->state_filter,
|
||||
&output_width, &output_height, width, height);
|
||||
|
||||
output_pitch = (output_width) * video_st->state_out_bpp;
|
||||
|
||||
rarch_softfilter_process(video_st->state_filter,
|
||||
video_st->state_buffer, output_pitch,
|
||||
data, width, height, pitch);
|
||||
|
||||
if (video_info.post_filter_record
|
||||
&& recording_st->data
|
||||
&& recording_st->driver
|
||||
&& recording_st->driver->push_video)
|
||||
recording_dump_frame(
|
||||
video_st->state_buffer,
|
||||
output_width, output_height, output_pitch,
|
||||
runloop_idle);
|
||||
|
||||
data = video_st->state_buffer;
|
||||
width = output_width;
|
||||
height = output_height;
|
||||
pitch = output_pitch;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (runloop_st->msg_queue_size > 0)
|
||||
{
|
||||
/* If widgets are currently enabled, then
|
||||
* messages were pushed to the queue before
|
||||
* widgets were initialised - in this case, the
|
||||
* first item in the message queue should be
|
||||
* extracted and pushed to the widget message
|
||||
* queue instead */
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
if (widgets_active)
|
||||
{
|
||||
msg_queue_entry_t msg_entry;
|
||||
bool msg_found = false;
|
||||
|
||||
RUNLOOP_MSG_QUEUE_LOCK(runloop_st);
|
||||
msg_found = msg_queue_extract(
|
||||
&runloop_st->msg_queue, &msg_entry);
|
||||
runloop_st->msg_queue_size = msg_queue_size(
|
||||
&runloop_st->msg_queue);
|
||||
RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st);
|
||||
|
||||
if (msg_found)
|
||||
gfx_widgets_msg_queue_push(
|
||||
NULL,
|
||||
msg_entry.msg,
|
||||
roundf((float)msg_entry.duration / 60.0f * 1000.0f),
|
||||
msg_entry.title,
|
||||
msg_entry.icon,
|
||||
msg_entry.category,
|
||||
msg_entry.prio,
|
||||
false,
|
||||
#ifdef HAVE_MENU
|
||||
menu_state_get_ptr()->alive
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
}
|
||||
/* ...otherwise, just output message via
|
||||
* regular OSD notification text (if enabled) */
|
||||
else if (video_info.font_enable)
|
||||
#else
|
||||
if (video_info.font_enable)
|
||||
#endif
|
||||
{
|
||||
const char *msg = NULL;
|
||||
RUNLOOP_MSG_QUEUE_LOCK(runloop_st);
|
||||
msg = msg_queue_pull(&runloop_st->msg_queue);
|
||||
runloop_st->msg_queue_size = msg_queue_size(&runloop_st->msg_queue);
|
||||
if (msg)
|
||||
strlcpy(video_driver_msg, msg, sizeof(video_driver_msg));
|
||||
RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st);
|
||||
}
|
||||
}
|
||||
|
||||
if (video_info.statistics_show)
|
||||
{
|
||||
audio_statistics_t audio_stats;
|
||||
double stddev = 0.0;
|
||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||
unsigned red = 255;
|
||||
unsigned green = 255;
|
||||
unsigned blue = 255;
|
||||
unsigned alpha = 255;
|
||||
|
||||
audio_stats.samples = 0;
|
||||
audio_stats.average_buffer_saturation = 0.0f;
|
||||
audio_stats.std_deviation_percentage = 0.0f;
|
||||
audio_stats.close_to_underrun = 0.0f;
|
||||
audio_stats.close_to_blocking = 0.0f;
|
||||
|
||||
video_monitor_fps_statistics(NULL, &stddev, NULL);
|
||||
|
||||
video_info.osd_stat_params.x = 0.010f;
|
||||
video_info.osd_stat_params.y = 0.950f;
|
||||
video_info.osd_stat_params.scale = 1.0f;
|
||||
video_info.osd_stat_params.full_screen = true;
|
||||
video_info.osd_stat_params.drop_x = -2;
|
||||
video_info.osd_stat_params.drop_y = -2;
|
||||
video_info.osd_stat_params.drop_mod = 0.3f;
|
||||
video_info.osd_stat_params.drop_alpha = 1.0f;
|
||||
video_info.osd_stat_params.color = COLOR_ABGR(
|
||||
red, green, blue, alpha);
|
||||
|
||||
audio_compute_buffer_statistics(&audio_stats);
|
||||
|
||||
snprintf(video_info.stat_text,
|
||||
sizeof(video_info.stat_text),
|
||||
"Video Statistics:\n -Frame rate: %6.2f fps\n -Frame time: %6.2f ms\n -Frame time deviation: %.3f %%\n"
|
||||
" -Frame count: %" PRIu64"\n -Viewport: %d x %d x %3.2f\n"
|
||||
"Audio Statistics:\n -Average buffer saturation: %.2f %%\n -Standard deviation: %.2f %%\n -Time spent close to underrun: %.2f %%\n -Time spent close to blocking: %.2f %%\n -Sample count: %d\n"
|
||||
"Core Geometry:\n -Size: %u x %u\n -Max Size: %u x %u\n -Aspect: %3.2f\nCore Timing:\n -FPS: %3.2f\n -Sample Rate: %6.2f\n",
|
||||
last_fps,
|
||||
frame_time / 1000.0f,
|
||||
100.0f * stddev,
|
||||
video_st->frame_count,
|
||||
video_info.width,
|
||||
video_info.height,
|
||||
video_info.refresh_rate,
|
||||
audio_stats.average_buffer_saturation,
|
||||
audio_stats.std_deviation_percentage,
|
||||
audio_stats.close_to_underrun,
|
||||
audio_stats.close_to_blocking,
|
||||
audio_stats.samples,
|
||||
av_info->geometry.base_width,
|
||||
av_info->geometry.base_height,
|
||||
av_info->geometry.max_width,
|
||||
av_info->geometry.max_height,
|
||||
av_info->geometry.aspect_ratio,
|
||||
av_info->timing.fps,
|
||||
av_info->timing.sample_rate);
|
||||
|
||||
/* TODO/FIXME - add OSD chat text here */
|
||||
}
|
||||
|
||||
if (video_st->current_video && video_st->current_video->frame)
|
||||
video_st->active = video_st->current_video->frame(
|
||||
video_st->data, data, width, height,
|
||||
video_st->frame_count, (unsigned)pitch,
|
||||
video_info.menu_screensaver_active ? "" : video_driver_msg,
|
||||
&video_info);
|
||||
|
||||
video_st->frame_count++;
|
||||
|
||||
/* Display the status text, with a higher priority. */
|
||||
if ( ( video_info.fps_show
|
||||
|| video_info.framecount_show
|
||||
|| video_info.memory_show
|
||||
|| video_info.core_status_msg_show
|
||||
)
|
||||
&& !video_info.menu_screensaver_active
|
||||
)
|
||||
{
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
if (widgets_active)
|
||||
strlcpy(
|
||||
dispwidget_get_ptr()->gfx_widgets_status_text,
|
||||
status_text,
|
||||
sizeof(dispwidget_get_ptr()->gfx_widgets_status_text)
|
||||
);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
runloop_msg_queue_push(status_text, 2, 1, true, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_CRTSWITCHRES)
|
||||
/* trigger set resolution*/
|
||||
if (video_info.crt_switch_resolution)
|
||||
{
|
||||
unsigned native_width = width;
|
||||
bool dynamic_super_width = false;
|
||||
|
||||
video_st->crt_switching_active = true;
|
||||
|
||||
switch (video_info.crt_switch_resolution_super)
|
||||
{
|
||||
case 2560:
|
||||
case 3840:
|
||||
case 1920:
|
||||
width = video_info.crt_switch_resolution_super;
|
||||
dynamic_super_width = false;
|
||||
break;
|
||||
case 1:
|
||||
dynamic_super_width = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
crt_switch_res_core(
|
||||
&video_st->crt_switch_st,
|
||||
native_width, width,
|
||||
height,
|
||||
video_st->core_hz,
|
||||
video_info.crt_switch_resolution,
|
||||
video_info.crt_switch_center_adjust,
|
||||
video_info.crt_switch_porch_adjust,
|
||||
video_info.monitor_index,
|
||||
dynamic_super_width,
|
||||
video_info.crt_switch_resolution_super,
|
||||
video_info.crt_switch_hires_menu);
|
||||
}
|
||||
else if (!video_info.crt_switch_resolution)
|
||||
#endif
|
||||
video_st->crt_switching_active = false;
|
||||
}
|
||||
|
@ -1399,6 +1399,20 @@ void video_driver_set_viewport_config(
|
||||
|
||||
void video_driver_set_viewport_square_pixel(struct retro_game_geometry *geom);
|
||||
|
||||
bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled);
|
||||
|
||||
/**
|
||||
* video_driver_frame:
|
||||
* @data : pointer to data of the video frame.
|
||||
* @width : width of the video frame.
|
||||
* @height : height of the video frame.
|
||||
* @pitch : pitch of the video frame.
|
||||
*
|
||||
* Video frame render callback function.
|
||||
**/
|
||||
void video_driver_frame(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch);
|
||||
|
||||
extern const video_driver_t *video_drivers[];
|
||||
|
||||
extern video_driver_t video_gl_core;
|
||||
|
804
retroarch.c
804
retroarch.c
@ -252,14 +252,6 @@
|
||||
#include "lakka.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define RUNLOOP_MSG_QUEUE_LOCK(runloop_st) slock_lock((runloop_st)->msg_queue_lock)
|
||||
#define RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st) slock_unlock((runloop_st)->msg_queue_lock)
|
||||
#else
|
||||
#define RUNLOOP_MSG_QUEUE_LOCK(runloop_st) (void)(runloop_st)
|
||||
#define RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st) (void)(runloop_st)
|
||||
#endif
|
||||
|
||||
/* Custom forward declarations */
|
||||
static bool recording_init(settings_t *settings,
|
||||
struct rarch_state *p_rarch);
|
||||
@ -5571,7 +5563,7 @@ static bool command_event_init_core(
|
||||
/* reset video format to libretro's default */
|
||||
video_st->pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555;
|
||||
|
||||
runloop_st->current_core.retro_set_environment(retroarch_environment_cb);
|
||||
runloop_st->current_core.retro_set_environment(runloop_environment_cb);
|
||||
|
||||
/* Load any input remap files
|
||||
* > Note that we always cache the current global
|
||||
@ -9013,17 +9005,7 @@ static core_option_manager_t *runloop_init_core_variables(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* retroarch_environment_cb:
|
||||
* @cmd : Identifier of command.
|
||||
* @data : Pointer to data.
|
||||
*
|
||||
* Environment callback function implementation.
|
||||
*
|
||||
* Returns: true (1) if environment callback command could
|
||||
* be performed, otherwise false (0).
|
||||
**/
|
||||
static bool retroarch_environment_cb(unsigned cmd, void *data)
|
||||
bool runloop_environment_cb(unsigned cmd, void *data)
|
||||
{
|
||||
unsigned p;
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
@ -10950,7 +10932,7 @@ static void libretro_get_environment_info(
|
||||
* Ignore any environment callbacks here in case we're running
|
||||
* on the non-current core. */
|
||||
runloop_st->ignore_environment_cb = true;
|
||||
func(retroarch_environment_cb);
|
||||
func(runloop_environment_cb);
|
||||
runloop_st->ignore_environment_cb = false;
|
||||
}
|
||||
|
||||
@ -11086,7 +11068,7 @@ static bool libretro_get_system_info(
|
||||
* Ignore any environment callbacks here in case we're running
|
||||
* on the non-current core. */
|
||||
runloop_st->ignore_environment_cb = true;
|
||||
retro_set_environment(retroarch_environment_cb);
|
||||
retro_set_environment(runloop_environment_cb);
|
||||
runloop_st->ignore_environment_cb = false;
|
||||
}
|
||||
|
||||
@ -11706,11 +11688,11 @@ end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool retroarch_environment_secondary_core_hook(
|
||||
static bool runloop_environment_secondary_core_hook(
|
||||
unsigned cmd, void *data)
|
||||
{
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
bool result = retroarch_environment_cb(cmd, data);
|
||||
bool result = runloop_environment_cb(cmd, data);
|
||||
|
||||
if (runloop_st->has_variable_update)
|
||||
{
|
||||
@ -11762,7 +11744,7 @@ static bool secondary_core_create(struct rarch_state *p_rarch,
|
||||
|
||||
runloop_st->secondary_core.symbols_inited = true;
|
||||
runloop_st->secondary_core.retro_set_environment(
|
||||
retroarch_environment_secondary_core_hook);
|
||||
runloop_environment_secondary_core_hook);
|
||||
#ifdef HAVE_RUNAHEAD
|
||||
runloop_st->has_variable_update = true;
|
||||
#endif
|
||||
@ -12053,7 +12035,7 @@ bool driver_wifi_connection_info(wifi_network_info_t *netinfo)
|
||||
return p_rarch->wifi_driver->connection_info(p_rarch->wifi_data, netinfo);
|
||||
}
|
||||
|
||||
wifi_network_scan_t* driver_wifi_get_ssids()
|
||||
wifi_network_scan_t* driver_wifi_get_ssids(void)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
return p_rarch->wifi_driver->get_ssids(p_rarch->wifi_data);
|
||||
@ -13193,335 +13175,6 @@ const char *config_get_audio_driver_options(void)
|
||||
}
|
||||
|
||||
/* VIDEO */
|
||||
/* Stub functions */
|
||||
|
||||
static bool video_driver_init_internal(
|
||||
settings_t *settings,
|
||||
bool *video_is_threaded,
|
||||
bool verbosity_enabled
|
||||
)
|
||||
{
|
||||
video_info_t video;
|
||||
unsigned max_dim, scale, width, height;
|
||||
video_viewport_t *custom_vp = NULL;
|
||||
input_driver_t *tmp = NULL;
|
||||
static uint16_t dummy_pixels[32] = {0};
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
input_driver_state_t *input_st = input_state_get_ptr();
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
struct retro_game_geometry *geom = &video_st->av_info.geometry;
|
||||
const enum retro_pixel_format
|
||||
video_driver_pix_fmt = video_st->pix_fmt;
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
const char *path_softfilter_plugin = settings->paths.path_softfilter_plugin;
|
||||
|
||||
if (!string_is_empty(path_softfilter_plugin))
|
||||
video_driver_init_filter(video_driver_pix_fmt, settings);
|
||||
#endif
|
||||
|
||||
max_dim = MAX(geom->max_width, geom->max_height);
|
||||
scale = next_pow2(max_dim) / RARCH_SCALE_BASE;
|
||||
scale = MAX(scale, 1);
|
||||
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
if (video_st->state_filter)
|
||||
scale = video_st->state_scale;
|
||||
#endif
|
||||
|
||||
/* Update core-dependent aspect ratio values. */
|
||||
video_driver_set_viewport_square_pixel(geom);
|
||||
video_driver_set_viewport_core();
|
||||
video_driver_set_viewport_config(geom,
|
||||
settings->floats.video_aspect_ratio,
|
||||
settings->bools.video_aspect_ratio_auto);
|
||||
|
||||
/* Update CUSTOM viewport. */
|
||||
custom_vp = &settings->video_viewport_custom;
|
||||
|
||||
if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
|
||||
{
|
||||
float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
|
||||
aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
|
||||
(custom_vp->width && custom_vp->height) ?
|
||||
(float)custom_vp->width / custom_vp->height : default_aspect;
|
||||
}
|
||||
|
||||
{
|
||||
/* Guard against aspect ratio index possibly being out of bounds */
|
||||
unsigned new_aspect_idx = settings->uints.video_aspect_ratio_idx;
|
||||
if (new_aspect_idx > ASPECT_RATIO_END)
|
||||
new_aspect_idx = settings->uints.video_aspect_ratio_idx = 0;
|
||||
|
||||
video_driver_set_aspect_ratio_value(
|
||||
aspectratio_lut[new_aspect_idx].value);
|
||||
}
|
||||
|
||||
if (settings->bools.video_fullscreen || video_st->force_fullscreen)
|
||||
{
|
||||
width = settings->uints.video_fullscreen_x;
|
||||
height = settings->uints.video_fullscreen_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
if (is_running_on_xbox())
|
||||
{
|
||||
width = settings->uints.video_fullscreen_x != 0 ? settings->uints.video_fullscreen_x : 3840;
|
||||
height = settings->uints.video_fullscreen_y != 0 ? settings->uints.video_fullscreen_y : 2160;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
|
||||
bool window_custom_size_enable = settings->bools.video_window_save_positions;
|
||||
#else
|
||||
bool window_custom_size_enable = settings->bools.video_window_custom_size_enable;
|
||||
#endif
|
||||
/* TODO: remove when the new window resizing core is hooked */
|
||||
if (window_custom_size_enable &&
|
||||
settings->uints.window_position_width &&
|
||||
settings->uints.window_position_height)
|
||||
{
|
||||
width = settings->uints.window_position_width;
|
||||
height = settings->uints.window_position_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
float video_scale = settings->floats.video_scale;
|
||||
/* Determine maximum allowed window dimensions
|
||||
* NOTE: We cannot read the actual display
|
||||
* metrics here, because the context driver
|
||||
* has not yet been initialised... */
|
||||
|
||||
/* > Try explicitly configured values */
|
||||
unsigned max_win_width = settings->uints.window_auto_width_max;
|
||||
unsigned max_win_height = settings->uints.window_auto_height_max;
|
||||
|
||||
/* > Handle invalid settings */
|
||||
if ((max_win_width == 0) || (max_win_height == 0))
|
||||
{
|
||||
/* > Try configured fullscreen width/height */
|
||||
max_win_width = settings->uints.video_fullscreen_x;
|
||||
max_win_height = settings->uints.video_fullscreen_y;
|
||||
|
||||
if ((max_win_width == 0) || (max_win_height == 0))
|
||||
{
|
||||
/* Maximum window width/size *must* be non-zero;
|
||||
* if all else fails, used defined default
|
||||
* maximum window size */
|
||||
max_win_width = DEFAULT_WINDOW_AUTO_WIDTH_MAX;
|
||||
max_win_height = DEFAULT_WINDOW_AUTO_HEIGHT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine nominal window size based on
|
||||
* core geometry */
|
||||
if (settings->bools.video_force_aspect)
|
||||
{
|
||||
/* Do rounding here to simplify integer
|
||||
* scale correctness. */
|
||||
unsigned base_width = roundf(geom->base_height *
|
||||
video_st->aspect_ratio);
|
||||
width = roundf(base_width * video_scale);
|
||||
}
|
||||
else
|
||||
width = roundf(geom->base_width * video_scale);
|
||||
|
||||
height = roundf(geom->base_height * video_scale);
|
||||
|
||||
/* Cap window size to maximum allowed values */
|
||||
if ((width > max_win_width) || (height > max_win_height))
|
||||
{
|
||||
unsigned geom_width = (width > 0) ? width : 1;
|
||||
unsigned geom_height = (height > 0) ? height : 1;
|
||||
float geom_aspect = (float)geom_width / (float)geom_height;
|
||||
float max_win_aspect = (float)max_win_width / (float)max_win_height;
|
||||
|
||||
if (geom_aspect > max_win_aspect)
|
||||
{
|
||||
width = max_win_width;
|
||||
height = geom_height * max_win_width / geom_width;
|
||||
/* Account for any possible rounding errors... */
|
||||
height = (height < 1) ? 1 : height;
|
||||
height = (height > max_win_height) ? max_win_height : height;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = max_win_height;
|
||||
width = geom_width * max_win_height / geom_height;
|
||||
/* Account for any possible rounding errors... */
|
||||
width = (width < 1) ? 1 : width;
|
||||
width = (width > max_win_width) ? max_win_width : width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (width && height)
|
||||
RARCH_LOG("[Video]: Video @ %ux%u\n", width, height);
|
||||
else
|
||||
RARCH_LOG("[Video]: Video @ fullscreen\n");
|
||||
|
||||
video_st->display_type = RARCH_DISPLAY_NONE;
|
||||
video_st->display = 0;
|
||||
video_st->display_userdata = 0;
|
||||
video_st->window = 0;
|
||||
|
||||
video_st->scaler_ptr = video_driver_pixel_converter_init(
|
||||
video_st->pix_fmt,
|
||||
VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st),
|
||||
RARCH_SCALE_BASE * scale);
|
||||
|
||||
video.width = width;
|
||||
video.height = height;
|
||||
video.fullscreen = settings->bools.video_fullscreen ||
|
||||
video_st->force_fullscreen;
|
||||
video.vsync = settings->bools.video_vsync &&
|
||||
!runloop_st->force_nonblock;
|
||||
video.force_aspect = settings->bools.video_force_aspect;
|
||||
video.font_enable = settings->bools.video_font_enable;
|
||||
video.swap_interval = settings->uints.video_swap_interval;
|
||||
video.adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
#ifdef GEKKO
|
||||
video.viwidth = settings->uints.video_viwidth;
|
||||
video.vfilter = settings->bools.video_vfilter;
|
||||
#endif
|
||||
video.smooth = settings->bools.video_smooth;
|
||||
video.ctx_scaling = settings->bools.video_ctx_scaling;
|
||||
video.input_scale = scale;
|
||||
video.font_size = settings->floats.video_font_size;
|
||||
video.path_font = settings->paths.path_font;
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
video.rgb32 =
|
||||
video_st->state_filter
|
||||
? video_st->state_out_rgb32
|
||||
: (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
#else
|
||||
video.rgb32 =
|
||||
(video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
#endif
|
||||
video.parent = 0;
|
||||
|
||||
video_st->started_fullscreen = video.fullscreen;
|
||||
/* Reset video frame count */
|
||||
video_st->frame_count = 0;
|
||||
|
||||
tmp = input_state_get_ptr()->current_driver;
|
||||
/* Need to grab the "real" video driver interface on a reinit. */
|
||||
video_driver_find_driver(settings,
|
||||
"video driver", verbosity_enabled);
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
video.is_threaded =
|
||||
VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
*video_is_threaded = video.is_threaded;
|
||||
|
||||
if (video.is_threaded)
|
||||
{
|
||||
bool ret;
|
||||
/* Can't do hardware rendering with threaded driver currently. */
|
||||
RARCH_LOG("[Video]: Starting threaded video driver ...\n");
|
||||
|
||||
ret = video_init_thread(
|
||||
(const video_driver_t**)&video_st->current_video,
|
||||
&video_st->data,
|
||||
&input_state_get_ptr()->current_driver,
|
||||
(void**)&input_state_get_ptr()->current_data,
|
||||
video_st->current_video,
|
||||
video);
|
||||
if (!ret)
|
||||
{
|
||||
RARCH_ERR("[Video]: Cannot open threaded video driver ... Exiting ...\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
video_st->data = video_st->current_video->init(
|
||||
&video,
|
||||
&input_state_get_ptr()->current_driver,
|
||||
(void**)&input_state_get_ptr()->current_data);
|
||||
|
||||
if (!video_st->data)
|
||||
{
|
||||
RARCH_ERR("[Video]: Cannot open video driver ... Exiting ...\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
video_st->poke = NULL;
|
||||
if (video_st->current_video->poke_interface)
|
||||
video_st->current_video->poke_interface(
|
||||
video_st->data, &video_st->poke);
|
||||
|
||||
if (video_st->current_video->viewport_info &&
|
||||
(!custom_vp->width ||
|
||||
!custom_vp->height))
|
||||
{
|
||||
/* Force custom viewport to have sane parameters. */
|
||||
custom_vp->width = width;
|
||||
custom_vp->height = height;
|
||||
|
||||
video_driver_get_viewport_info(custom_vp);
|
||||
}
|
||||
|
||||
video_driver_set_rotation(retroarch_get_rotation() % 4);
|
||||
|
||||
video_st->current_video->suppress_screensaver(video_st->data,
|
||||
settings->bools.ui_suspend_screensaver_enable);
|
||||
|
||||
if (!video_driver_init_input(tmp, settings, verbosity_enabled))
|
||||
return false;
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
input_overlay_deinit();
|
||||
input_overlay_init();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
if (settings->bools.video_layout_enable)
|
||||
{
|
||||
video_layout_init(video_st->data,
|
||||
video_driver_layout_render_interface());
|
||||
video_layout_load(settings->paths.path_video_layout);
|
||||
video_layout_view_select(settings->uints.video_layout_selected_view);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!runloop_st->current_core.game_loaded)
|
||||
video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8);
|
||||
|
||||
#if defined(PSP)
|
||||
video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f);
|
||||
#endif
|
||||
|
||||
video_context_driver_reset();
|
||||
|
||||
video_display_server_init(video_st->display_type);
|
||||
|
||||
if ((enum rotation)settings->uints.screen_orientation != ORIENTATION_NORMAL)
|
||||
video_display_server_set_screen_orientation((enum rotation)settings->uints.screen_orientation);
|
||||
|
||||
/* Ensure that we preserve the 'grab mouse'
|
||||
* state if it was enabled prior to driver
|
||||
* (re-)initialisation */
|
||||
if (input_st->grab_mouse_state)
|
||||
{
|
||||
video_driver_hide_mouse();
|
||||
if (input_driver_grab_mouse())
|
||||
input_st->grab_mouse_state = true;
|
||||
}
|
||||
else if (video.fullscreen)
|
||||
{
|
||||
video_driver_hide_mouse();
|
||||
if (!settings->bools.video_windowed_fullscreen)
|
||||
if (input_driver_grab_mouse())
|
||||
input_st->grab_mouse_state = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void video_driver_reinit_context(struct rarch_state *p_rarch,
|
||||
settings_t *settings, int flags)
|
||||
{
|
||||
@ -13557,443 +13210,6 @@ void video_driver_reinit(int flags)
|
||||
video_st->cache_context = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* video_driver_frame:
|
||||
* @data : pointer to data of the video frame.
|
||||
* @width : width of the video frame.
|
||||
* @height : height of the video frame.
|
||||
* @pitch : pitch of the video frame.
|
||||
*
|
||||
* Video frame render callback function.
|
||||
**/
|
||||
static void video_driver_frame(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch)
|
||||
{
|
||||
char status_text[128];
|
||||
static char video_driver_msg[256];
|
||||
static retro_time_t curr_time;
|
||||
static retro_time_t fps_time;
|
||||
static float last_fps, frame_time;
|
||||
static uint64_t last_used_memory, last_total_memory;
|
||||
retro_time_t new_time;
|
||||
video_frame_info_t video_info;
|
||||
video_driver_state_t *video_st= video_state_get_ptr();
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
const enum retro_pixel_format
|
||||
video_driver_pix_fmt = video_st->pix_fmt;
|
||||
bool runloop_idle = runloop_st->idle;
|
||||
bool video_driver_active = video_st->active;
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
bool widgets_active = dispwidget_get_ptr()->active;
|
||||
#endif
|
||||
|
||||
status_text[0] = '\0';
|
||||
video_driver_msg[0] = '\0';
|
||||
|
||||
if (!video_driver_active)
|
||||
return;
|
||||
|
||||
new_time = cpu_features_get_time_usec();
|
||||
|
||||
if (data)
|
||||
video_st->frame_cache_data = data;
|
||||
video_st->frame_cache_width = width;
|
||||
video_st->frame_cache_height = height;
|
||||
video_st->frame_cache_pitch = pitch;
|
||||
|
||||
if (
|
||||
video_st->scaler_ptr
|
||||
&& data
|
||||
&& (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555)
|
||||
&& (data != RETRO_HW_FRAME_BUFFER_VALID)
|
||||
&& video_pixel_frame_scale(
|
||||
video_st->scaler_ptr->scaler,
|
||||
video_st->scaler_ptr->scaler_out,
|
||||
data, width, height, pitch)
|
||||
)
|
||||
{
|
||||
data = video_st->scaler_ptr->scaler_out;
|
||||
pitch = video_st->scaler_ptr->scaler->out_stride;
|
||||
}
|
||||
|
||||
video_driver_build_info(&video_info);
|
||||
|
||||
/* Get the amount of frames per seconds. */
|
||||
if (video_st->frame_count)
|
||||
{
|
||||
unsigned fps_update_interval =
|
||||
video_info.fps_update_interval;
|
||||
unsigned memory_update_interval =
|
||||
video_info.memory_update_interval;
|
||||
size_t buf_pos = 1;
|
||||
/* set this to 1 to avoid an offset issue */
|
||||
unsigned write_index =
|
||||
video_st->frame_time_count++ &
|
||||
(MEASURE_FRAME_TIME_SAMPLES_COUNT - 1);
|
||||
frame_time = new_time - fps_time;
|
||||
video_st->frame_time_samples
|
||||
[write_index] = frame_time;
|
||||
fps_time = new_time;
|
||||
|
||||
if (video_info.fps_show)
|
||||
buf_pos = snprintf(
|
||||
status_text, sizeof(status_text),
|
||||
"FPS: %6.2f", last_fps);
|
||||
|
||||
if (video_info.framecount_show)
|
||||
{
|
||||
char frames_text[64];
|
||||
if (status_text[buf_pos-1] != '\0')
|
||||
strlcat(status_text, " || ", sizeof(status_text));
|
||||
snprintf(frames_text,
|
||||
sizeof(frames_text),
|
||||
"%s: %" PRIu64, msg_hash_to_str(MSG_FRAMES),
|
||||
(uint64_t)video_st->frame_count);
|
||||
buf_pos = strlcat(status_text, frames_text, sizeof(status_text));
|
||||
}
|
||||
|
||||
if (video_info.memory_show)
|
||||
{
|
||||
char mem[128];
|
||||
|
||||
if ((video_st->frame_count % memory_update_interval) == 0)
|
||||
{
|
||||
last_total_memory = frontend_driver_get_total_memory();
|
||||
last_used_memory = last_total_memory - frontend_driver_get_free_memory();
|
||||
}
|
||||
|
||||
mem[0] = '\0';
|
||||
snprintf(
|
||||
mem, sizeof(mem), "MEM: %.2f/%.2fMB", last_used_memory / (1024.0f * 1024.0f),
|
||||
last_total_memory / (1024.0f * 1024.0f));
|
||||
if (status_text[buf_pos-1] != '\0')
|
||||
strlcat(status_text, " || ", sizeof(status_text));
|
||||
strlcat(status_text, mem, sizeof(status_text));
|
||||
}
|
||||
|
||||
if ((video_st->frame_count % fps_update_interval) == 0)
|
||||
{
|
||||
last_fps = TIME_TO_FPS(curr_time, new_time,
|
||||
fps_update_interval);
|
||||
|
||||
strlcpy(video_st->window_title,
|
||||
video_st->title_buf,
|
||||
sizeof(video_st->window_title));
|
||||
|
||||
if (!string_is_empty(status_text))
|
||||
{
|
||||
strlcat(video_st->window_title,
|
||||
" || ", sizeof(video_st->window_title));
|
||||
strlcat(video_st->window_title,
|
||||
status_text, sizeof(video_st->window_title));
|
||||
}
|
||||
|
||||
curr_time = new_time;
|
||||
video_st->window_title_update = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_time = fps_time = new_time;
|
||||
|
||||
strlcpy(video_st->window_title,
|
||||
video_st->title_buf,
|
||||
sizeof(video_st->window_title));
|
||||
|
||||
if (video_info.fps_show)
|
||||
strlcpy(status_text,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
|
||||
sizeof(status_text));
|
||||
|
||||
video_st->window_title_update = true;
|
||||
}
|
||||
|
||||
/* Add core status message to status text */
|
||||
if (video_info.core_status_msg_show)
|
||||
{
|
||||
/* Note: We need to lock a mutex here. Strictly
|
||||
* speaking, runloop_core_status_msg is not part
|
||||
* of the message queue, but:
|
||||
* - It may be implemented as a queue in the future
|
||||
* - It seems unnecessary to create a new slock_t
|
||||
* object for this type of message when
|
||||
* _runloop_msg_queue_lock is already available
|
||||
* We therefore just call runloop_msg_queue_lock()/
|
||||
* runloop_msg_queue_unlock() in this case */
|
||||
RUNLOOP_MSG_QUEUE_LOCK(runloop_st);
|
||||
|
||||
/* Check whether duration timer has elapsed */
|
||||
runloop_st->core_status_msg.duration -= anim_get_ptr()->delta_time;
|
||||
|
||||
if (runloop_st->core_status_msg.duration < 0.0f)
|
||||
{
|
||||
runloop_st->core_status_msg.str[0] = '\0';
|
||||
runloop_st->core_status_msg.priority = 0;
|
||||
runloop_st->core_status_msg.duration = 0.0f;
|
||||
runloop_st->core_status_msg.set = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If status text is already set, add status
|
||||
* message at the end */
|
||||
if (!string_is_empty(status_text))
|
||||
{
|
||||
strlcat(status_text,
|
||||
" || ", sizeof(status_text));
|
||||
strlcat(status_text,
|
||||
runloop_st->core_status_msg.str,
|
||||
sizeof(status_text));
|
||||
}
|
||||
else
|
||||
strlcpy(status_text,
|
||||
runloop_st->core_status_msg.str,
|
||||
sizeof(status_text));
|
||||
}
|
||||
|
||||
RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st);
|
||||
}
|
||||
|
||||
/* Slightly messy code,
|
||||
* but we really need to do processing before blocking on VSync
|
||||
* for best possible scheduling.
|
||||
*/
|
||||
if (
|
||||
(
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
!video_st->state_filter ||
|
||||
#endif
|
||||
!video_info.post_filter_record
|
||||
|| !data
|
||||
|| video_st->record_gpu_buffer
|
||||
) && recording_state.data
|
||||
&& recording_state.driver
|
||||
&& recording_state.driver->push_video)
|
||||
recording_dump_frame(
|
||||
data, width, height,
|
||||
pitch, runloop_idle);
|
||||
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
if (data && video_st->state_filter)
|
||||
{
|
||||
unsigned output_width = 0;
|
||||
unsigned output_height = 0;
|
||||
unsigned output_pitch = 0;
|
||||
|
||||
rarch_softfilter_get_output_size(video_st->state_filter,
|
||||
&output_width, &output_height, width, height);
|
||||
|
||||
output_pitch = (output_width) * video_st->state_out_bpp;
|
||||
|
||||
rarch_softfilter_process(video_st->state_filter,
|
||||
video_st->state_buffer, output_pitch,
|
||||
data, width, height, pitch);
|
||||
|
||||
if (video_info.post_filter_record
|
||||
&& recording_state.data
|
||||
&& recording_state.driver
|
||||
&& recording_state.driver->push_video)
|
||||
recording_dump_frame(
|
||||
video_st->state_buffer,
|
||||
output_width, output_height, output_pitch,
|
||||
runloop_idle);
|
||||
|
||||
data = video_st->state_buffer;
|
||||
width = output_width;
|
||||
height = output_height;
|
||||
pitch = output_pitch;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (runloop_st->msg_queue_size > 0)
|
||||
{
|
||||
/* If widgets are currently enabled, then
|
||||
* messages were pushed to the queue before
|
||||
* widgets were initialised - in this case, the
|
||||
* first item in the message queue should be
|
||||
* extracted and pushed to the widget message
|
||||
* queue instead */
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
if (widgets_active)
|
||||
{
|
||||
msg_queue_entry_t msg_entry;
|
||||
bool msg_found = false;
|
||||
|
||||
RUNLOOP_MSG_QUEUE_LOCK(runloop_st);
|
||||
msg_found = msg_queue_extract(
|
||||
&runloop_st->msg_queue, &msg_entry);
|
||||
runloop_st->msg_queue_size = msg_queue_size(
|
||||
&runloop_st->msg_queue);
|
||||
RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st);
|
||||
|
||||
if (msg_found)
|
||||
gfx_widgets_msg_queue_push(
|
||||
NULL,
|
||||
msg_entry.msg,
|
||||
roundf((float)msg_entry.duration / 60.0f * 1000.0f),
|
||||
msg_entry.title,
|
||||
msg_entry.icon,
|
||||
msg_entry.category,
|
||||
msg_entry.prio,
|
||||
false,
|
||||
#ifdef HAVE_MENU
|
||||
menu_state_get_ptr()->alive
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
}
|
||||
/* ...otherwise, just output message via
|
||||
* regular OSD notification text (if enabled) */
|
||||
else if (video_info.font_enable)
|
||||
#else
|
||||
if (video_info.font_enable)
|
||||
#endif
|
||||
{
|
||||
const char *msg = NULL;
|
||||
RUNLOOP_MSG_QUEUE_LOCK(runloop_st);
|
||||
msg = msg_queue_pull(&runloop_st->msg_queue);
|
||||
runloop_st->msg_queue_size = msg_queue_size(&runloop_st->msg_queue);
|
||||
if (msg)
|
||||
strlcpy(video_driver_msg, msg, sizeof(video_driver_msg));
|
||||
RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st);
|
||||
}
|
||||
}
|
||||
|
||||
if (video_info.statistics_show)
|
||||
{
|
||||
audio_statistics_t audio_stats;
|
||||
double stddev = 0.0;
|
||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||
unsigned red = 255;
|
||||
unsigned green = 255;
|
||||
unsigned blue = 255;
|
||||
unsigned alpha = 255;
|
||||
|
||||
audio_stats.samples = 0;
|
||||
audio_stats.average_buffer_saturation = 0.0f;
|
||||
audio_stats.std_deviation_percentage = 0.0f;
|
||||
audio_stats.close_to_underrun = 0.0f;
|
||||
audio_stats.close_to_blocking = 0.0f;
|
||||
|
||||
video_monitor_fps_statistics(NULL, &stddev, NULL);
|
||||
|
||||
video_info.osd_stat_params.x = 0.010f;
|
||||
video_info.osd_stat_params.y = 0.950f;
|
||||
video_info.osd_stat_params.scale = 1.0f;
|
||||
video_info.osd_stat_params.full_screen = true;
|
||||
video_info.osd_stat_params.drop_x = -2;
|
||||
video_info.osd_stat_params.drop_y = -2;
|
||||
video_info.osd_stat_params.drop_mod = 0.3f;
|
||||
video_info.osd_stat_params.drop_alpha = 1.0f;
|
||||
video_info.osd_stat_params.color = COLOR_ABGR(
|
||||
red, green, blue, alpha);
|
||||
|
||||
audio_compute_buffer_statistics(&audio_stats);
|
||||
|
||||
snprintf(video_info.stat_text,
|
||||
sizeof(video_info.stat_text),
|
||||
"Video Statistics:\n -Frame rate: %6.2f fps\n -Frame time: %6.2f ms\n -Frame time deviation: %.3f %%\n"
|
||||
" -Frame count: %" PRIu64"\n -Viewport: %d x %d x %3.2f\n"
|
||||
"Audio Statistics:\n -Average buffer saturation: %.2f %%\n -Standard deviation: %.2f %%\n -Time spent close to underrun: %.2f %%\n -Time spent close to blocking: %.2f %%\n -Sample count: %d\n"
|
||||
"Core Geometry:\n -Size: %u x %u\n -Max Size: %u x %u\n -Aspect: %3.2f\nCore Timing:\n -FPS: %3.2f\n -Sample Rate: %6.2f\n",
|
||||
last_fps,
|
||||
frame_time / 1000.0f,
|
||||
100.0f * stddev,
|
||||
video_st->frame_count,
|
||||
video_info.width,
|
||||
video_info.height,
|
||||
video_info.refresh_rate,
|
||||
audio_stats.average_buffer_saturation,
|
||||
audio_stats.std_deviation_percentage,
|
||||
audio_stats.close_to_underrun,
|
||||
audio_stats.close_to_blocking,
|
||||
audio_stats.samples,
|
||||
av_info->geometry.base_width,
|
||||
av_info->geometry.base_height,
|
||||
av_info->geometry.max_width,
|
||||
av_info->geometry.max_height,
|
||||
av_info->geometry.aspect_ratio,
|
||||
av_info->timing.fps,
|
||||
av_info->timing.sample_rate);
|
||||
|
||||
/* TODO/FIXME - add OSD chat text here */
|
||||
}
|
||||
|
||||
if (video_st->current_video && video_st->current_video->frame)
|
||||
video_st->active = video_st->current_video->frame(
|
||||
video_st->data, data, width, height,
|
||||
video_st->frame_count, (unsigned)pitch,
|
||||
video_info.menu_screensaver_active ? "" : video_driver_msg,
|
||||
&video_info);
|
||||
|
||||
video_st->frame_count++;
|
||||
|
||||
/* Display the status text, with a higher priority. */
|
||||
if ( ( video_info.fps_show
|
||||
|| video_info.framecount_show
|
||||
|| video_info.memory_show
|
||||
|| video_info.core_status_msg_show
|
||||
)
|
||||
&& !video_info.menu_screensaver_active
|
||||
)
|
||||
{
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
if (widgets_active)
|
||||
strlcpy(
|
||||
dispwidget_get_ptr()->gfx_widgets_status_text,
|
||||
status_text,
|
||||
sizeof(dispwidget_get_ptr()->gfx_widgets_status_text)
|
||||
);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
runloop_msg_queue_push(status_text, 2, 1, true, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_CRTSWITCHRES)
|
||||
/* trigger set resolution*/
|
||||
if (video_info.crt_switch_resolution)
|
||||
{
|
||||
unsigned native_width = width;
|
||||
bool dynamic_super_width = false;
|
||||
|
||||
video_st->crt_switching_active = true;
|
||||
|
||||
switch (video_info.crt_switch_resolution_super)
|
||||
{
|
||||
case 2560:
|
||||
case 3840:
|
||||
case 1920:
|
||||
width = video_info.crt_switch_resolution_super;
|
||||
dynamic_super_width = false;
|
||||
break;
|
||||
case 1:
|
||||
dynamic_super_width = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
crt_switch_res_core(
|
||||
&video_st->crt_switch_st,
|
||||
native_width, width,
|
||||
height,
|
||||
video_st->core_hz,
|
||||
video_info.crt_switch_resolution,
|
||||
video_info.crt_switch_center_adjust,
|
||||
video_info.crt_switch_porch_adjust,
|
||||
video_info.monitor_index,
|
||||
dynamic_super_width,
|
||||
video_info.crt_switch_resolution_super,
|
||||
video_info.crt_switch_hires_menu);
|
||||
}
|
||||
else if (!video_info.crt_switch_resolution)
|
||||
#endif
|
||||
video_st->crt_switching_active = false;
|
||||
}
|
||||
|
||||
void crt_switch_driver_refresh(void)
|
||||
{
|
||||
/*video_context_driver_reset();*/
|
||||
@ -14274,7 +13490,7 @@ static void drivers_init(
|
||||
video_driver_filter_free();
|
||||
#endif
|
||||
video_driver_set_cached_frame_ptr(NULL);
|
||||
if (!video_driver_init_internal(settings, &video_is_threaded,
|
||||
if (!video_driver_init_internal(&video_is_threaded,
|
||||
verbosity_enabled))
|
||||
retroarch_fail(p_rarch, 1, "video_driver_init_internal()");
|
||||
|
||||
@ -17826,7 +17042,7 @@ static enum runloop_state_enum runloop_check_state(
|
||||
{
|
||||
float target_hz = 0.0;
|
||||
|
||||
retroarch_environment_cb(
|
||||
runloop_environment_cb(
|
||||
RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE, &target_hz);
|
||||
|
||||
runloop_msg_queue_push(msg_hash_to_str(MSG_PRESS_AGAIN_TO_QUIT), 1,
|
||||
|
@ -59,8 +59,6 @@
|
||||
|
||||
#define DEBUG_INFO_FILENAME "debug_info.txt"
|
||||
|
||||
#define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time)))
|
||||
|
||||
#define DEFAULT_NETWORK_GAMEPAD_PORT 55400
|
||||
#define UDP_FRAME_PACKETS 16
|
||||
|
||||
|
@ -47,8 +47,6 @@ static bool secondary_core_ensure_exists(struct rarch_state *p_rarch,
|
||||
static int16_t input_state_get_last(unsigned port,
|
||||
unsigned device, unsigned index, unsigned id);
|
||||
#endif
|
||||
static void video_driver_frame(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch);
|
||||
static void retro_frame_null(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch);
|
||||
static void retro_run_null(void);
|
||||
@ -77,8 +75,6 @@ static void drivers_init(struct rarch_state *p_rarch,
|
||||
static bool core_load(unsigned poll_type_behavior);
|
||||
static bool core_unload_game(void);
|
||||
|
||||
static bool retroarch_environment_cb(unsigned cmd, void *data);
|
||||
|
||||
static void driver_camera_stop(void);
|
||||
static bool driver_camera_start(void);
|
||||
|
||||
|
20
runloop.h
20
runloop.h
@ -45,6 +45,14 @@
|
||||
/* Arbitrary 10 roms for each subsystem limit */
|
||||
#define SUBSYSTEM_MAX_SUBSYSTEM_ROMS 10
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define RUNLOOP_MSG_QUEUE_LOCK(runloop_st) slock_lock((runloop_st)->msg_queue_lock)
|
||||
#define RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st) slock_unlock((runloop_st)->msg_queue_lock)
|
||||
#else
|
||||
#define RUNLOOP_MSG_QUEUE_LOCK(runloop_st) (void)(runloop_st)
|
||||
#define RUNLOOP_MSG_QUEUE_UNLOCK(runloop_st) (void)(runloop_st)
|
||||
#endif
|
||||
|
||||
enum runloop_state_enum
|
||||
{
|
||||
RUNLOOP_STATE_ITERATE = 0,
|
||||
@ -288,6 +296,18 @@ RETRO_BEGIN_DECLS
|
||||
|
||||
void runloop_path_fill_names(void);
|
||||
|
||||
/**
|
||||
* runloop_environment_cb:
|
||||
* @cmd : Identifier of command.
|
||||
* @data : Pointer to data.
|
||||
*
|
||||
* Environment callback function implementation.
|
||||
*
|
||||
* Returns: true (1) if environment callback command could
|
||||
* be performed, otherwise false (0).
|
||||
**/
|
||||
bool runloop_environment_cb(unsigned cmd, void *data);
|
||||
|
||||
runloop_state_t *runloop_state_get_ptr(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
Loading…
x
Reference in New Issue
Block a user