diff --git a/gfx/gfx_display.c b/gfx/gfx_display.c index cf777073a2..f64a0987d4 100644 --- a/gfx/gfx_display.c +++ b/gfx/gfx_display.c @@ -525,6 +525,49 @@ font_data_t *gfx_display_font_file( return font_data; } +/* Draw text on top of the screen */ +void gfx_display_draw_text( + const font_data_t *font, const char *text, + float x, float y, int width, int height, + uint32_t color, enum text_alignment text_align, + float scale, bool shadows_enable, float shadow_offset, + bool draw_outside) +{ + struct font_params params; + video_driver_state_t *video_st = video_state_get_ptr(); + + if ((color & 0x000000FF) == 0) + return; + + /* Don't draw outside of the screen */ + if (!draw_outside && + ((x < -64 || x > width + 64) + || (y < -64 || y > height + 64)) + ) + return; + + params.x = x / width; + params.y = 1.0f - y / height; + params.scale = scale; + params.drop_mod = 0.0f; + params.drop_x = 0.0f; + params.drop_y = 0.0f; + params.color = color; + params.full_screen = true; + params.text_align = text_align; + + if (shadows_enable) + { + params.drop_x = shadow_offset; + params.drop_y = -shadow_offset; + params.drop_alpha = 0.35f; + } + + if (video_st->poke && video_st->poke->set_osd_msg) + video_st->poke->set_osd_msg(video_st->data, + text, ¶ms, (void*)font); +} + void gfx_display_draw_bg( gfx_display_t *p_disp, gfx_display_ctx_draw_t *draw, diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 8fa9608922..9205047d59 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include "../config.h" @@ -32,6 +33,7 @@ #include "../frontend/frontend_driver.h" #include "../ui/ui_companion_driver.h" +#include "../driver.h" #include "../file_path_special.h" #include "../list_special.h" #include "../retroarch.h" @@ -1335,3 +1337,885 @@ VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st); video_monitor_compute_fps_statistics(video_st->frame_time_count); } + +void video_driver_set_viewport_config( + struct retro_game_geometry *geom, + float video_aspect_ratio, + bool video_aspect_ratio_auto) +{ + if (video_aspect_ratio < 0.0f) + { + if (geom->aspect_ratio > 0.0f && video_aspect_ratio_auto) + aspectratio_lut[ASPECT_RATIO_CONFIG].value = geom->aspect_ratio; + else + { + unsigned base_width = geom->base_width; + unsigned base_height = geom->base_height; + + /* Get around division by zero errors */ + if (base_width == 0) + base_width = 1; + if (base_height == 0) + base_height = 1; + aspectratio_lut[ASPECT_RATIO_CONFIG].value = + (float)base_width / base_height; /* 1:1 PAR. */ + } + } + else + aspectratio_lut[ASPECT_RATIO_CONFIG].value = video_aspect_ratio; +} + +void video_driver_set_viewport_square_pixel(struct retro_game_geometry *geom) +{ + unsigned len, i, aspect_x, aspect_y; + unsigned int rotation = 0; + unsigned highest = 1; + unsigned width = geom->base_width; + unsigned height = geom->base_height; + + if (width == 0 || height == 0) + return; + + rotation = retroarch_get_rotation(); + len = MIN(width, height); + + for (i = 1; i < len; i++) + { + if ((width % i) == 0 && (height % i) == 0) + highest = i; + } + + if (rotation % 2) + { + aspect_x = height / highest; + aspect_y = width / highest; + } + else + { + aspect_x = width / highest; + aspect_y = height / highest; + } + + snprintf(aspectratio_lut[ASPECT_RATIO_SQUARE].name, + sizeof(aspectratio_lut[ASPECT_RATIO_SQUARE].name), + "1:1 PAR (%u:%u DAR)", aspect_x, aspect_y); + + aspectratio_lut[ASPECT_RATIO_SQUARE].value = (float)aspect_x / aspect_y; +} + +void video_driver_set_viewport(unsigned width, unsigned height, + bool force_fullscreen, bool allow_rotate) +{ + video_driver_state_t *video_st = &video_driver_st; + if (video_st->current_video && video_st->current_video->set_viewport) + video_st->current_video->set_viewport( + video_st->data, width, height, + force_fullscreen, allow_rotate); +} + +bool video_driver_set_rotation(unsigned rotation) +{ + video_driver_state_t *video_st = &video_driver_st; + if (!video_st->current_video || !video_st->current_video->set_rotation) + return false; + video_st->current_video->set_rotation(video_st->data, rotation); + return true; +} + +bool video_driver_set_video_mode(unsigned width, + unsigned height, bool fullscreen) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_video_mode) + { + video_st->poke->set_video_mode(video_st->data, + width, height, fullscreen); + return true; + } + return false; +} + +bool video_driver_get_video_output_size(unsigned *width, unsigned *height, char *desc, size_t desc_len) +{ + video_driver_state_t *video_st = &video_driver_st; + if (!video_st->poke || !video_st->poke->get_video_output_size) + return false; + video_st->poke->get_video_output_size(video_st->data, + width, height, desc, desc_len); + return true; +} + +void video_driver_set_texture_enable(bool enable, bool fullscreen) +{ + video_driver_state_t *video_st = &video_driver_st; + if (video_st->poke && video_st->poke->set_texture_enable) + video_st->poke->set_texture_enable(video_st->data, + enable, fullscreen); +} + +void video_driver_set_texture_frame(const void *frame, bool rgb32, + unsigned width, unsigned height, float alpha) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_texture_frame) + video_st->poke->set_texture_frame(video_st->data, + frame, rgb32, width, height, alpha); +} + + +#ifdef HAVE_VIDEO_LAYOUT +const video_layout_render_interface_t *video_driver_layout_render_interface(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( !video_st->current_video || + !video_st->current_video->video_layout_render_interface) + return NULL; + + return video_st->current_video->video_layout_render_interface( + video_st->data); +} +#endif + +void *video_driver_read_frame_raw(unsigned *width, + unsigned *height, size_t *pitch) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->current_video + && video_st->current_video->read_frame_raw) + return video_st->current_video->read_frame_raw( + video_st->data, width, + height, pitch); + return NULL; +} + +void video_driver_set_filtering(unsigned index, + bool smooth, bool ctx_scaling) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_filtering) + video_st->poke->set_filtering( + video_st->data, + index, smooth, ctx_scaling); +} + +void video_driver_set_hdr_max_nits(float max_nits) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_hdr_max_nits) + video_st->poke->set_hdr_max_nits(video_st->data, max_nits); +} + +void video_driver_set_hdr_paper_white_nits(float paper_white_nits) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_hdr_paper_white_nits) + video_st->poke->set_hdr_paper_white_nits(video_st->data, paper_white_nits); +} + +void video_driver_set_hdr_contrast(float contrast) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_hdr_contrast) + video_st->poke->set_hdr_contrast(video_st->data, + VIDEO_HDR_MAX_CONTRAST - contrast); +} + +void video_driver_set_hdr_expand_gamut(bool expand_gamut) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->set_hdr_expand_gamut) + video_st->poke->set_hdr_expand_gamut(video_st->data, expand_gamut); +} + +/* Use this value as a replacement for anywhere + * where a pure white colour value is used in the UI. + * + * When HDR is turned on 1,1,1,1 should never really + * be used as this is peak brightness and could cause + * damage to displays over long periods of time + * and be quite hard to look at on really bright displays. + * + * Use paper white instead which is always defined as + * 0.5, 0.5, 0.5, 1.0 or in other words is the top of + * the old SDR (Standard Dynamic Range) range + */ +unsigned video_driver_get_hdr_paper_white(void) +{ + /* 0.5, 0.5, 0.5, 1 */ + if ( video_driver_supports_hdr() + && config_get_ptr()->bools.video_hdr_enable) + return 0x7f7f7fff; + return 0xffffffff; +} + +/* Same as above but returns the white value in floats */ +float *video_driver_get_hdr_paper_white_float(void) +{ + static float paper_white[4] = { 0.5f, 0.5f, 0.5f, 1.0f}; + static float sdr_white [4] = { 1.0f, 1.0f, 1.0f, 1.0f}; + if( video_driver_supports_hdr() + && config_get_ptr()->bools.video_hdr_enable) + return paper_white; + return sdr_white; +} + +/* This is useful to create a HDR (High Dynamic Range) white + * based off of some passed in nit level - say you want a + * slightly brighter than paper white value for some parts + * of the UI + */ +float video_driver_get_hdr_luminance(float nits) +{ + settings_t *settings = config_get_ptr(); + if(video_driver_supports_hdr() && settings->bools.video_hdr_enable) + { + float luminance = nits / + settings->floats.video_hdr_paper_white_nits; + return luminance / (1.0f + luminance); + } + return nits; +} + +/* Get reinhard tone mapped colour value for UI elements + * when using HDR and its inverse tonemapper - normally don't use + * but useful if you want a specific colour to look the same + * after inverse tonemapping has been applied */ +unsigned video_driver_get_hdr_color(unsigned color) +{ + if( video_driver_supports_hdr() + && config_get_ptr()->bools.video_hdr_enable) + { + float luminance; + float rgb[3]; + float yxy[3]; + + rgb[0] = (float)((color >> 24) & 0xFF) / 255.0f; + rgb[1] = (float)((color >> 16) & 0xFF) / 255.0f; + rgb[2] = (float)((color >> 8 ) & 0xFF) / 255.0f; + + convert_rgb_to_yxy(rgb, yxy); + + /* TODO: We should probably scale this by average luminance */ + luminance = yxy[0]; + yxy[0] = luminance / (1.0f + luminance); + + convert_yxy_to_rgb(rgb, yxy); + + return ( (unsigned)(saturate_value(rgb[0]) * 255.0f) << 24) + | ((unsigned)(saturate_value(rgb[1]) * 255.0f) << 16) + | ((unsigned)(saturate_value(rgb[2]) * 255.0f) << 8) + | (color & 0xFF); + } + return color; +} + +void video_driver_cached_frame_set(const void *data, unsigned width, + unsigned height, size_t pitch) +{ + video_driver_state_t *video_st= &video_driver_st; + 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; +} + +void video_driver_cached_frame_get(const void **data, unsigned *width, + unsigned *height, size_t *pitch) +{ + video_driver_state_t *video_st= &video_driver_st; + if (data) + *data = video_st->frame_cache_data; + if (width) + *width = video_st->frame_cache_width; + if (height) + *height = video_st->frame_cache_height; + if (pitch) + *pitch = video_st->frame_cache_pitch; +} + +void video_driver_get_size(unsigned *width, unsigned *height) +{ +#ifdef HAVE_THREADS + video_driver_state_t *video_st = &video_driver_st; + bool is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st); + + VIDEO_DRIVER_THREADED_LOCK(video_st, is_threaded); +#endif + if (width) + *width = video_st->width; + if (height) + *height = video_st->height; +#ifdef HAVE_THREADS + VIDEO_DRIVER_THREADED_UNLOCK(video_st, is_threaded); +#endif +} + +void video_driver_set_size(unsigned width, unsigned height) +{ + video_driver_state_t *video_st = &video_driver_st; +#ifdef HAVE_THREADS + bool is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st); + VIDEO_DRIVER_THREADED_LOCK(video_st, is_threaded); +#endif + video_st->width = width; + video_st->height = height; +#ifdef HAVE_THREADS + VIDEO_DRIVER_THREADED_UNLOCK(video_st, is_threaded); +#endif +} + +/** + * video_monitor_fps_statistics + * @refresh_rate : Monitor refresh rate. + * @deviation : Deviation from measured refresh rate. + * @sample_points : Amount of sampled points. + * + * Gets the monitor FPS statistics based on the current + * runtime. + * + * Returns: true (1) on success. + * false (0) if: + * a) threaded video mode is enabled + * b) less than 2 frame time samples. + * c) FPS monitor enable is off. + **/ +bool video_monitor_fps_statistics(double *refresh_rate, + double *deviation, unsigned *sample_points) +{ + unsigned i; + retro_time_t accum = 0; + retro_time_t avg = 0; + retro_time_t accum_var = 0; + unsigned samples = 0; + video_driver_state_t *video_st = &video_driver_st; + +#ifdef HAVE_THREADS + if (VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st)) + return false; +#endif + + samples = MIN(MEASURE_FRAME_TIME_SAMPLES_COUNT, + (unsigned)video_st->frame_time_count); + + if (samples < 2) + return false; + + /* Measure statistics on frame time (microsecs), *not* FPS. */ + for (i = 0; i < samples; i++) + { + accum += video_st->frame_time_samples[i]; +#if 0 + RARCH_LOG("[Video]: Interval #%u: %d usec / frame.\n", + i, (int)frame_time_samples[i]); +#endif + } + + avg = accum / samples; + + /* Drop first measurement. It is likely to be bad. */ + for (i = 0; i < samples; i++) + { + retro_time_t diff = video_st->frame_time_samples[i] - avg; + accum_var += diff * diff; + } + + *deviation = sqrt((double)accum_var / (samples - 1)) / avg; + + if (refresh_rate) + *refresh_rate = 1000000.0 / avg; + + if (sample_points) + *sample_points = samples; + + return true; +} + +float video_driver_get_aspect_ratio(void) +{ + video_driver_state_t *video_st = &video_driver_st; + return video_st->aspect_ratio; +} + +void video_driver_set_aspect_ratio_value(float value) +{ + video_driver_state_t *video_st = &video_driver_st; + video_st->aspect_ratio = value; +} + +enum retro_pixel_format video_driver_get_pixel_format(void) +{ + video_driver_state_t *video_st = &video_driver_st; + return video_st->pix_fmt; +} + +void video_driver_lock_new(void) +{ + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK_FREE(video_st); +#ifdef HAVE_THREADS + if (!video_st->display_lock) + video_st->display_lock = slock_new(); + retro_assert(video_st->display_lock); + + if (!video_st->context_lock) + video_st->context_lock = slock_new(); + retro_assert(video_st->context_lock); +#endif +} + +void video_driver_set_cached_frame_ptr(const void *data) +{ + video_driver_state_t *video_st = &video_driver_st; + video_st->frame_cache_data = data; +} + +void video_driver_set_stub_frame(void) +{ + video_driver_state_t *video_st = &video_driver_st; + video_st->frame_bak = video_st->current_video->frame; + video_st->current_video->frame = video_null.frame; +} + +void video_driver_unset_stub_frame(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if (video_st->frame_bak) + video_st->current_video->frame = video_st->frame_bak; + + video_st->frame_bak = NULL; +} + +bool video_driver_supports_viewport_read(void) +{ + video_driver_state_t *video_st = &video_driver_st; + return video_st->current_video->read_viewport + && video_st->current_video->viewport_info; +} + +bool video_driver_prefer_viewport_read(void) +{ + video_driver_state_t *video_st = &video_driver_st; + settings_t *settings = config_get_ptr(); +#ifdef HAVE_SCREENSHOTS + bool video_gpu_screenshot = settings->bools.video_gpu_screenshot; + if (video_gpu_screenshot) + return true; +#endif + return (video_driver_is_hw_context() && + !video_st->current_video->read_frame_raw); +} + +bool video_driver_supports_read_frame_raw(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if (video_st->current_video->read_frame_raw) + return true; + return false; +} + +void video_driver_set_viewport_core(void) +{ + video_driver_state_t *video_st = &video_driver_st; + struct retro_game_geometry *geom = &video_st->av_info.geometry; + + if (!geom || geom->base_width <= 0.0f || geom->base_height <= 0.0f) + return; + + /* Fallback to 1:1 pixel ratio if none provided */ + if (geom->aspect_ratio > 0.0f) + aspectratio_lut[ASPECT_RATIO_CORE].value = geom->aspect_ratio; + else + aspectratio_lut[ASPECT_RATIO_CORE].value = + (float)geom->base_width / geom->base_height; +} + +void video_driver_set_rgba(void) +{ + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK(video_st); + video_st->use_rgba = true; + VIDEO_DRIVER_UNLOCK(video_st); +} + +void video_driver_unset_rgba(void) +{ + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK(video_st); + video_st->use_rgba = false; + VIDEO_DRIVER_UNLOCK(video_st); +} + +bool video_driver_supports_rgba(void) +{ + bool tmp; + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK(video_st); + tmp = video_st->use_rgba; + VIDEO_DRIVER_UNLOCK(video_st); + return tmp; +} + +void video_driver_set_hdr_support(void) +{ + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK(video_st); + video_st->hdr_support = true; + VIDEO_DRIVER_UNLOCK(video_st); +} + +void video_driver_unset_hdr_support(void) +{ + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK(video_st); + video_st->hdr_support = false; + VIDEO_DRIVER_UNLOCK(video_st); +} + +bool video_driver_supports_hdr(void) +{ + bool tmp; + video_driver_state_t *video_st = &video_driver_st; + VIDEO_DRIVER_LOCK(video_st); + tmp = video_st->hdr_support; + VIDEO_DRIVER_UNLOCK(video_st); + return tmp; +} + +bool video_driver_get_next_video_out(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( !video_st->poke + || !video_st->poke->get_video_output_next + ) + return false; + video_st->poke->get_video_output_next(video_st->data); + return true; +} + +bool video_driver_get_prev_video_out(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( + !video_st->poke + || !video_st->poke->get_video_output_prev + ) + return false; + + video_st->poke->get_video_output_prev(video_st->data); + return true; +} + +void video_driver_monitor_reset(void) +{ + video_driver_state_t *video_st = &video_driver_st; + video_st->frame_time_count = 0; +} + +void video_driver_set_aspect_ratio(void) +{ + settings_t *settings = config_get_ptr(); + video_driver_state_t *video_st = &video_driver_st; + unsigned aspect_ratio_idx = settings->uints.video_aspect_ratio_idx; + + switch (aspect_ratio_idx) + { + case ASPECT_RATIO_SQUARE: + video_driver_set_viewport_square_pixel(&video_st->av_info.geometry); + break; + + case ASPECT_RATIO_CORE: + video_driver_set_viewport_core(); + break; + + case ASPECT_RATIO_CONFIG: + video_driver_set_viewport_config( + &video_st->av_info.geometry, + settings->floats.video_aspect_ratio, + settings->bools.video_aspect_ratio_auto); + break; + + case ASPECT_RATIO_FULL: + { + unsigned width = video_st->width; + unsigned height = video_st->height; + + if (width != 0 && height != 0) + aspectratio_lut[ASPECT_RATIO_FULL].value = (float)width / (float)height; + } + break; + + default: + break; + } + + video_driver_set_aspect_ratio_value( + aspectratio_lut[aspect_ratio_idx].value); + + if ( video_st->poke + && video_st->poke->set_aspect_ratio) + video_st->poke->set_aspect_ratio(video_st->data, aspect_ratio_idx); +} + +void video_driver_update_viewport( + struct video_viewport* vp, bool force_full, bool keep_aspect) +{ + float device_aspect = (float)vp->full_width / vp->full_height; + settings_t *settings = config_get_ptr(); + bool video_scale_integer = settings->bools.video_scale_integer; + unsigned video_aspect_ratio_idx = settings->uints.video_aspect_ratio_idx; + video_driver_state_t *video_st = &video_driver_st; + float video_driver_aspect_ratio = video_st->aspect_ratio; + + vp->x = 0; + vp->y = 0; + vp->width = vp->full_width; + vp->height = vp->full_height; + + if (video_scale_integer && !force_full) + video_viewport_get_scaled_integer( + vp, + vp->full_width, + vp->full_height, + video_driver_aspect_ratio, keep_aspect); + else if (keep_aspect && !force_full) + { + float desired_aspect = video_driver_aspect_ratio; + +#if defined(HAVE_MENU) + if (video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) + { + const struct video_viewport *custom = &settings->video_viewport_custom; + + vp->x = custom->x; + vp->y = custom->y; + vp->width = custom->width; + vp->height = custom->height; + } + else +#endif + { + float delta; + + if (fabsf(device_aspect - desired_aspect) < 0.0001f) + { + /* If the aspect ratios of screen and desired aspect + * ratio are sufficiently equal (floating point stuff), + * assume they are actually equal. + */ + } + else if (device_aspect > desired_aspect) + { + delta = (desired_aspect / device_aspect - 1.0f) + / 2.0f + 0.5f; + vp->x = (int)roundf(vp->full_width * (0.5f - delta)); + vp->width = (unsigned)roundf(2.0f * vp->full_width * delta); + vp->y = 0; + vp->height = vp->full_height; + } + else + { + vp->x = 0; + vp->width = vp->full_width; + delta = (device_aspect / desired_aspect - 1.0f) + / 2.0f + 0.5f; + vp->y = (int)roundf(vp->full_height * (0.5f - delta)); + vp->height = (unsigned)roundf(2.0f * vp->full_height * delta); + } + } + } + +#if defined(RARCH_MOBILE) + /* In portrait mode, we want viewport to gravitate to top of screen. */ + if (device_aspect < 1.0f) + vp->y = 0; +#endif +} + +void video_driver_show_mouse(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->show_mouse) + video_st->poke->show_mouse(video_st->data, true); +} + +void video_driver_hide_mouse(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->show_mouse) + video_st->poke->show_mouse(video_st->data, false); +} + +void video_driver_restore_cached(void *settings_data) +{ + settings_t *settings = (settings_t*)settings_data; + video_driver_state_t *video_st = &video_driver_st; + if (video_st->cached_driver_id[0]) + { + configuration_set_string(settings, + settings->arrays.video_driver, video_st->cached_driver_id); + + video_st->cached_driver_id[0] = 0; + RARCH_LOG("[Video]: Restored video driver to \"%s\".\n", + settings->arrays.video_driver); + } +} + +bool video_driver_find_driver( + void *settings_data, + const char *prefix, bool verbosity_enabled) +{ + int i; + settings_t *settings = (settings_t*)settings_data; + video_driver_state_t *video_st = &video_driver_st; + + if (video_driver_is_hw_context()) + { + struct retro_hw_render_callback *hwr = + VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st); + int rdr_major = hwr->version_major; + int rdr_minor = hwr->version_minor; + const char *rdr_context_name = hw_render_context_name(hwr->context_type, rdr_major, rdr_minor); + enum retro_hw_context_type rdr_type = hw_render_context_type(rdr_context_name); + + video_st->current_video = NULL; + + if (hwr) + { + switch (rdr_type) + { + case RETRO_HW_CONTEXT_OPENGL_CORE: + case RETRO_HW_CONTEXT_VULKAN: + case RETRO_HW_CONTEXT_DIRECT3D: +#if defined(HAVE_VULKAN) || defined(HAVE_D3D11) || defined(HAVE_D3D9) || defined(HAVE_OPENGL_CORE) + RARCH_LOG("[Video]: Using HW render, %s driver forced.\n", + rdr_context_name); + + if (!string_is_equal(settings->arrays.video_driver, + rdr_context_name)) + { + strlcpy(video_st->cached_driver_id, + settings->arrays.video_driver, + sizeof(video_st->cached_driver_id)); + configuration_set_string(settings, + settings->arrays.video_driver, + rdr_context_name); + RARCH_LOG("[Video]: \"%s\" saved as cached driver.\n", + settings->arrays.video_driver); + } + + video_st->current_video = hw_render_context_driver(rdr_type, rdr_major, rdr_minor); + return true; +#else + break; +#endif + case RETRO_HW_CONTEXT_OPENGL: +#if defined(HAVE_OPENGL) + RARCH_LOG("[Video]: Using HW render, OpenGL driver forced.\n"); + + /* If we have configured one of the HW render + * capable GL drivers, go with that. */ +#if defined(HAVE_OPENGL_CORE) + if ( !string_is_equal(settings->arrays.video_driver, "gl") && + !string_is_equal(settings->arrays.video_driver, "glcore")) + { + strlcpy(video_st->cached_driver_id, + settings->arrays.video_driver, + sizeof(video_st->cached_driver_id)); + configuration_set_string(settings, + settings->arrays.video_driver, + "glcore"); + RARCH_LOG("[Video]: \"%s\" saved as cached driver.\n", + settings->arrays.video_driver); + video_st->current_video = &video_gl_core; + return true; + } +#else + if ( !string_is_equal(settings->arrays.video_driver, "gl")) + { + strlcpy(video_st->cached_driver_id, + settings->arrays.video_driver, + sizeof(video_st->cached_driver_id)); + configuration_set_string(settings, + settings->arrays.video_driver, + "gl"); + RARCH_LOG("[Video]: \"%s\" saved as cached driver.\n", + settings->arrays.video_driver); + video_st->current_video = &video_gl2; + return true; + } +#endif + + RARCH_LOG("[Video]: Using configured \"%s\"" + " driver for GL HW render.\n", + settings->arrays.video_driver); + break; +#endif + default: + case RETRO_HW_CONTEXT_NONE: + break; + } + } + } + + if (frontend_driver_has_get_video_driver_func()) + { + if ((video_st->current_video = (video_driver_t*) + frontend_driver_get_video_driver())) + return true; + + RARCH_WARN("[Video]: Frontend supports get_video_driver() but did not specify one.\n"); + } + + i = (int)driver_find_index( + "video_driver", + settings->arrays.video_driver); + + if (i >= 0) + video_st->current_video = (video_driver_t*)video_drivers[i]; + else + { + if (verbosity_enabled) + { + unsigned d; + RARCH_ERR("Couldn't find any %s named \"%s\"\n", prefix, + settings->arrays.video_driver); + RARCH_LOG_OUTPUT("Available %ss are:\n", prefix); + for (d = 0; video_drivers[d]; d++) + RARCH_LOG_OUTPUT("\t%s\n", video_drivers[d]->ident); + RARCH_WARN("Going to default to first %s...\n", prefix); + } + + if (!(video_st->current_video = (video_driver_t*)video_drivers[0])) + return false; + } + return true; +} + +void video_driver_apply_state_changes(void) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->poke + && video_st->poke->apply_state_changes) + video_st->poke->apply_state_changes(video_st->data); +} + +bool video_driver_read_viewport(uint8_t *buffer, bool is_idle) +{ + video_driver_state_t *video_st = &video_driver_st; + if ( video_st->current_video->read_viewport + && video_st->current_video->read_viewport( + video_st->data, buffer, is_idle)) + return true; + return false; +} diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 16fb53c39b..30bd09a4cc 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -1444,6 +1444,21 @@ void video_driver_filter_free(void); void *video_thread_get_ptr(video_driver_state_t *video_st); #endif +void video_driver_lock_new(void); + +bool video_driver_find_driver( + void *settings_data, + const char *prefix, bool verbosity_enabled); + +void video_driver_restore_cached(void *settings_data); + +void video_driver_set_viewport_config( + struct retro_game_geometry *geom, + float video_aspect_ratio, + bool video_aspect_ratio_auto); + +void video_driver_set_viewport_square_pixel(struct retro_game_geometry *geom); + extern const video_driver_t *video_drivers[]; extern video_driver_t video_gl_core; diff --git a/retroarch.c b/retroarch.c index 7e6c069de3..3ee179292a 100644 --- a/retroarch.c +++ b/retroarch.c @@ -15181,71 +15181,6 @@ void audio_driver_menu_sample(void) /* VIDEO */ /* Stub functions */ -static void video_driver_set_viewport_config( - struct retro_game_geometry *geom, - float video_aspect_ratio, - bool video_aspect_ratio_auto) -{ - if (video_aspect_ratio < 0.0f) - { - if (geom->aspect_ratio > 0.0f && video_aspect_ratio_auto) - aspectratio_lut[ASPECT_RATIO_CONFIG].value = geom->aspect_ratio; - else - { - unsigned base_width = geom->base_width; - unsigned base_height = geom->base_height; - - /* Get around division by zero errors */ - if (base_width == 0) - base_width = 1; - if (base_height == 0) - base_height = 1; - aspectratio_lut[ASPECT_RATIO_CONFIG].value = - (float)base_width / base_height; /* 1:1 PAR. */ - } - } - else - aspectratio_lut[ASPECT_RATIO_CONFIG].value = video_aspect_ratio; -} - -static void video_driver_set_viewport_square_pixel(struct retro_game_geometry *geom) -{ - unsigned len, i, aspect_x, aspect_y; - unsigned int rotation = 0; - unsigned highest = 1; - unsigned width = geom->base_width; - unsigned height = geom->base_height; - - if (width == 0 || height == 0) - return; - - rotation = retroarch_get_rotation(); - len = MIN(width, height); - - for (i = 1; i < len; i++) - { - if ((width % i) == 0 && (height % i) == 0) - highest = i; - } - - if (rotation % 2) - { - aspect_x = height / highest; - aspect_y = width / highest; - } - else - { - aspect_x = width / highest; - aspect_y = height / highest; - } - - snprintf(aspectratio_lut[ASPECT_RATIO_SQUARE].name, - sizeof(aspectratio_lut[ASPECT_RATIO_SQUARE].name), - "1:1 PAR (%u:%u DAR)", aspect_x, aspect_y); - - aspectratio_lut[ASPECT_RATIO_SQUARE].value = (float)aspect_x / aspect_y; -} - static bool video_driver_init_internal( struct rarch_state *p_rarch, settings_t *settings, @@ -15573,403 +15508,6 @@ VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st); return true; } -void video_driver_set_viewport(unsigned width, unsigned height, - bool force_fullscreen, bool allow_rotate) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (video_st->current_video && video_st->current_video->set_viewport) - video_st->current_video->set_viewport( - video_st->data, width, height, - force_fullscreen, allow_rotate); -} - -bool video_driver_set_rotation(unsigned rotation) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (!video_st->current_video || !video_st->current_video->set_rotation) - return false; - video_st->current_video->set_rotation(video_st->data, rotation); - return true; -} - -bool video_driver_set_video_mode(unsigned width, - unsigned height, bool fullscreen) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_video_mode) - { - video_st->poke->set_video_mode(video_st->data, - width, height, fullscreen); - return true; - } - return false; -} - -bool video_driver_get_video_output_size(unsigned *width, unsigned *height, char *desc, size_t desc_len) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (!video_st->poke || !video_st->poke->get_video_output_size) - return false; - video_st->poke->get_video_output_size(video_st->data, - width, height, desc, desc_len); - return true; -} - -/* Draw text on top of the screen */ -void gfx_display_draw_text( - const font_data_t *font, const char *text, - float x, float y, int width, int height, - uint32_t color, enum text_alignment text_align, - float scale, bool shadows_enable, float shadow_offset, - bool draw_outside) -{ - struct font_params params; - video_driver_state_t *video_st = video_state_get_ptr(); - - if ((color & 0x000000FF) == 0) - return; - - /* Don't draw outside of the screen */ - if (!draw_outside && - ((x < -64 || x > width + 64) - || (y < -64 || y > height + 64)) - ) - return; - - params.x = x / width; - params.y = 1.0f - y / height; - params.scale = scale; - params.drop_mod = 0.0f; - params.drop_x = 0.0f; - params.drop_y = 0.0f; - params.color = color; - params.full_screen = true; - params.text_align = text_align; - - if (shadows_enable) - { - params.drop_x = shadow_offset; - params.drop_y = -shadow_offset; - params.drop_alpha = 0.35f; - } - - if (video_st->poke && video_st->poke->set_osd_msg) - video_st->poke->set_osd_msg(video_st->data, - text, ¶ms, (void*)font); -} - -void video_driver_set_texture_enable(bool enable, bool fullscreen) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (video_st->poke && video_st->poke->set_texture_enable) - video_st->poke->set_texture_enable(video_st->data, - enable, fullscreen); -} - -void video_driver_set_texture_frame(const void *frame, bool rgb32, - unsigned width, unsigned height, float alpha) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_texture_frame) - video_st->poke->set_texture_frame(video_st->data, - frame, rgb32, width, height, alpha); -} - - -#ifdef HAVE_VIDEO_LAYOUT -const video_layout_render_interface_t *video_driver_layout_render_interface(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( !video_st->current_video || - !video_st->current_video->video_layout_render_interface) - return NULL; - - return video_st->current_video->video_layout_render_interface( - video_st->data); -} -#endif - -void *video_driver_read_frame_raw(unsigned *width, - unsigned *height, size_t *pitch) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->current_video - && video_st->current_video->read_frame_raw) - return video_st->current_video->read_frame_raw( - video_st->data, width, - height, pitch); - return NULL; -} - -void video_driver_set_filtering(unsigned index, - bool smooth, bool ctx_scaling) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_filtering) - video_st->poke->set_filtering( - video_st->data, - index, smooth, ctx_scaling); -} - -void video_driver_set_hdr_max_nits(float max_nits) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_hdr_max_nits) - video_st->poke->set_hdr_max_nits(video_st->data, max_nits); -} - -void video_driver_set_hdr_paper_white_nits(float paper_white_nits) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_hdr_paper_white_nits) - video_st->poke->set_hdr_paper_white_nits(video_st->data, paper_white_nits); -} - -void video_driver_set_hdr_contrast(float contrast) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_hdr_contrast) - video_st->poke->set_hdr_contrast(video_st->data, - VIDEO_HDR_MAX_CONTRAST - contrast); -} - -void video_driver_set_hdr_expand_gamut(bool expand_gamut) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->set_hdr_expand_gamut) - video_st->poke->set_hdr_expand_gamut(video_st->data, expand_gamut); -} - -/* Use this value as a replacement for anywhere - * where a pure white colour value is used in the UI. - * - * When HDR is turned on 1,1,1,1 should never really - * be used as this is peak brightness and could cause - * damage to displays over long periods of time - * and be quite hard to look at on really bright displays. - * - * Use paper white instead which is always defined as - * 0.5, 0.5, 0.5, 1.0 or in other words is the top of - * the old SDR (Standard Dynamic Range) range - */ -unsigned video_driver_get_hdr_paper_white(void) -{ - /* 0.5, 0.5, 0.5, 1 */ - if ( video_driver_supports_hdr() - && config_get_ptr()->bools.video_hdr_enable) - return 0x7f7f7fff; - return 0xffffffff; -} - -/* Same as above but returns the white value in floats */ -float *video_driver_get_hdr_paper_white_float(void) -{ - static float paper_white[4] = { 0.5f, 0.5f, 0.5f, 1.0f}; - static float sdr_white [4] = { 1.0f, 1.0f, 1.0f, 1.0f}; - if( video_driver_supports_hdr() - && config_get_ptr()->bools.video_hdr_enable) - return paper_white; - return sdr_white; -} - -/* This is useful to create a HDR (High Dynamic Range) white - * based off of some passed in nit level - say you want a - * slightly brighter than paper white value for some parts - * of the UI - */ -float video_driver_get_hdr_luminance(float nits) -{ - settings_t *settings = config_get_ptr(); - if(video_driver_supports_hdr() && settings->bools.video_hdr_enable) - { - float luminance = nits / - settings->floats.video_hdr_paper_white_nits; - return luminance / (1.0f + luminance); - } - return nits; -} - -/* Get reinhard tone mapped colour value for UI elements - * when using HDR and its inverse tonemapper - normally don't use - * but useful if you want a specific colour to look the same - * after inverse tonemapping has been applied */ -unsigned video_driver_get_hdr_color(unsigned color) -{ - if( video_driver_supports_hdr() - && config_get_ptr()->bools.video_hdr_enable) - { - float luminance; - float rgb[3]; - float yxy[3]; - - rgb[0] = (float)((color >> 24) & 0xFF) / 255.0f; - rgb[1] = (float)((color >> 16) & 0xFF) / 255.0f; - rgb[2] = (float)((color >> 8 ) & 0xFF) / 255.0f; - - convert_rgb_to_yxy(rgb, yxy); - - /* TODO: We should probably scale this by average luminance */ - luminance = yxy[0]; - yxy[0] = luminance / (1.0f + luminance); - - convert_yxy_to_rgb(rgb, yxy); - - return ( (unsigned)(saturate_value(rgb[0]) * 255.0f) << 24) - | ((unsigned)(saturate_value(rgb[1]) * 255.0f) << 16) - | ((unsigned)(saturate_value(rgb[2]) * 255.0f) << 8) - | (color & 0xFF); - } - return color; -} - -void video_driver_cached_frame_set(const void *data, unsigned width, - unsigned height, size_t pitch) -{ - video_driver_state_t *video_st= video_state_get_ptr(); - 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; -} - -void video_driver_cached_frame_get(const void **data, unsigned *width, - unsigned *height, size_t *pitch) -{ - video_driver_state_t *video_st= video_state_get_ptr(); - if (data) - *data = video_st->frame_cache_data; - if (width) - *width = video_st->frame_cache_width; - if (height) - *height = video_st->frame_cache_height; - if (pitch) - *pitch = video_st->frame_cache_pitch; -} - -void video_driver_get_size(unsigned *width, unsigned *height) -{ -#ifdef HAVE_THREADS - video_driver_state_t *video_st= video_state_get_ptr(); - bool is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st); - - VIDEO_DRIVER_THREADED_LOCK(video_st, is_threaded); -#endif - if (width) - *width = video_st->width; - if (height) - *height = video_st->height; -#ifdef HAVE_THREADS - VIDEO_DRIVER_THREADED_UNLOCK(video_st, is_threaded); -#endif -} - -void video_driver_set_size(unsigned width, unsigned height) -{ - video_driver_state_t *video_st= video_state_get_ptr(); -#ifdef HAVE_THREADS - bool is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st); - VIDEO_DRIVER_THREADED_LOCK(video_st, is_threaded); -#endif - video_st->width = width; - video_st->height = height; -#ifdef HAVE_THREADS - VIDEO_DRIVER_THREADED_UNLOCK(video_st, is_threaded); -#endif -} - -/** - * video_monitor_fps_statistics - * @refresh_rate : Monitor refresh rate. - * @deviation : Deviation from measured refresh rate. - * @sample_points : Amount of sampled points. - * - * Gets the monitor FPS statistics based on the current - * runtime. - * - * Returns: true (1) on success. - * false (0) if: - * a) threaded video mode is enabled - * b) less than 2 frame time samples. - * c) FPS monitor enable is off. - **/ -bool video_monitor_fps_statistics(double *refresh_rate, - double *deviation, unsigned *sample_points) -{ - unsigned i; - retro_time_t accum = 0; - retro_time_t avg = 0; - retro_time_t accum_var = 0; - unsigned samples = 0; - video_driver_state_t *video_st = video_state_get_ptr(); - -#ifdef HAVE_THREADS - if (VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st)) - return false; -#endif - - samples = MIN(MEASURE_FRAME_TIME_SAMPLES_COUNT, - (unsigned)video_st->frame_time_count); - - if (samples < 2) - return false; - - /* Measure statistics on frame time (microsecs), *not* FPS. */ - for (i = 0; i < samples; i++) - { - accum += video_st->frame_time_samples[i]; -#if 0 - RARCH_LOG("[Video]: Interval #%u: %d usec / frame.\n", - i, (int)frame_time_samples[i]); -#endif - } - - avg = accum / samples; - - /* Drop first measurement. It is likely to be bad. */ - for (i = 0; i < samples; i++) - { - retro_time_t diff = video_st->frame_time_samples[i] - avg; - accum_var += diff * diff; - } - - *deviation = sqrt((double)accum_var / (samples - 1)) / avg; - - if (refresh_rate) - *refresh_rate = 1000000.0 / avg; - - if (sample_points) - *sample_points = samples; - - return true; -} - -float video_driver_get_aspect_ratio(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - return video_st->aspect_ratio; -} - -void video_driver_set_aspect_ratio_value(float value) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - video_st->aspect_ratio = value; -} - -enum retro_pixel_format video_driver_get_pixel_format(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - return video_st->pix_fmt; -} - /** * video_driver_cached_frame: * @@ -15997,467 +15535,6 @@ void video_driver_cached_frame(void) recording_state.data = recording; } -static void video_driver_lock_new(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK_FREE(video_st); -#ifdef HAVE_THREADS - if (!video_st->display_lock) - video_st->display_lock = slock_new(); - retro_assert(video_st->display_lock); - - if (!video_st->context_lock) - video_st->context_lock = slock_new(); - retro_assert(video_st->context_lock); -#endif -} - -void video_driver_set_cached_frame_ptr(const void *data) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - video_st->frame_cache_data = data; -} - -void video_driver_set_stub_frame(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - video_st->frame_bak = video_st->current_video->frame; - video_st->current_video->frame = video_null.frame; -} - -void video_driver_unset_stub_frame(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (video_st->frame_bak) - video_st->current_video->frame = video_st->frame_bak; - - video_st->frame_bak = NULL; -} - -bool video_driver_supports_viewport_read(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - return video_st->current_video->read_viewport - && video_st->current_video->viewport_info; -} - -bool video_driver_prefer_viewport_read(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - settings_t *settings = config_get_ptr(); -#ifdef HAVE_SCREENSHOTS - bool video_gpu_screenshot = settings->bools.video_gpu_screenshot; - if (video_gpu_screenshot) - return true; -#endif - return (video_driver_is_hw_context() && - !video_st->current_video->read_frame_raw); -} - -bool video_driver_supports_read_frame_raw(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (video_st->current_video->read_frame_raw) - return true; - return false; -} - -void video_driver_set_viewport_core(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - struct retro_game_geometry *geom = &video_st->av_info.geometry; - - if (!geom || geom->base_width <= 0.0f || geom->base_height <= 0.0f) - return; - - /* Fallback to 1:1 pixel ratio if none provided */ - if (geom->aspect_ratio > 0.0f) - aspectratio_lut[ASPECT_RATIO_CORE].value = geom->aspect_ratio; - else - aspectratio_lut[ASPECT_RATIO_CORE].value = - (float)geom->base_width / geom->base_height; -} - -void video_driver_set_rgba(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK(video_st); - video_st->use_rgba = true; - VIDEO_DRIVER_UNLOCK(video_st); -} - -void video_driver_unset_rgba(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK(video_st); - video_st->use_rgba = false; - VIDEO_DRIVER_UNLOCK(video_st); -} - -bool video_driver_supports_rgba(void) -{ - bool tmp; - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK(video_st); - tmp = video_st->use_rgba; - VIDEO_DRIVER_UNLOCK(video_st); - return tmp; -} - -void video_driver_set_hdr_support(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK(video_st); - video_st->hdr_support = true; - VIDEO_DRIVER_UNLOCK(video_st); -} - -void video_driver_unset_hdr_support(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK(video_st); - video_st->hdr_support = false; - VIDEO_DRIVER_UNLOCK(video_st); -} - -bool video_driver_supports_hdr(void) -{ - bool tmp; - video_driver_state_t *video_st = video_state_get_ptr(); - VIDEO_DRIVER_LOCK(video_st); - tmp = video_st->hdr_support; - VIDEO_DRIVER_UNLOCK(video_st); - return tmp; -} - -bool video_driver_get_next_video_out(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( !video_st->poke - || !video_st->poke->get_video_output_next - ) - return false; - video_st->poke->get_video_output_next(video_st->data); - return true; -} - -bool video_driver_get_prev_video_out(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( - !video_st->poke - || !video_st->poke->get_video_output_prev - ) - return false; - - video_st->poke->get_video_output_prev(video_st->data); - return true; -} - -void video_driver_monitor_reset(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - video_st->frame_time_count = 0; -} - -void video_driver_set_aspect_ratio(void) -{ - settings_t *settings = config_get_ptr(); - video_driver_state_t *video_st = video_state_get_ptr(); - unsigned aspect_ratio_idx = settings->uints.video_aspect_ratio_idx; - - switch (aspect_ratio_idx) - { - case ASPECT_RATIO_SQUARE: - video_driver_set_viewport_square_pixel(&video_st->av_info.geometry); - break; - - case ASPECT_RATIO_CORE: - video_driver_set_viewport_core(); - break; - - case ASPECT_RATIO_CONFIG: - video_driver_set_viewport_config( - &video_st->av_info.geometry, - settings->floats.video_aspect_ratio, - settings->bools.video_aspect_ratio_auto); - break; - - case ASPECT_RATIO_FULL: - { - unsigned width = video_st->width; - unsigned height = video_st->height; - - if (width != 0 && height != 0) - aspectratio_lut[ASPECT_RATIO_FULL].value = (float)width / (float)height; - } - break; - - default: - break; - } - - video_driver_set_aspect_ratio_value( - aspectratio_lut[aspect_ratio_idx].value); - - if ( video_st->poke - && video_st->poke->set_aspect_ratio) - video_st->poke->set_aspect_ratio(video_st->data, aspect_ratio_idx); -} - -void video_driver_update_viewport( - struct video_viewport* vp, bool force_full, bool keep_aspect) -{ - float device_aspect = (float)vp->full_width / vp->full_height; - settings_t *settings = config_get_ptr(); - bool video_scale_integer = settings->bools.video_scale_integer; - unsigned video_aspect_ratio_idx = settings->uints.video_aspect_ratio_idx; - video_driver_state_t *video_st = video_state_get_ptr(); - float video_driver_aspect_ratio = video_st->aspect_ratio; - - vp->x = 0; - vp->y = 0; - vp->width = vp->full_width; - vp->height = vp->full_height; - - if (video_scale_integer && !force_full) - video_viewport_get_scaled_integer( - vp, - vp->full_width, - vp->full_height, - video_driver_aspect_ratio, keep_aspect); - else if (keep_aspect && !force_full) - { - float desired_aspect = video_driver_aspect_ratio; - -#if defined(HAVE_MENU) - if (video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) - { - const struct video_viewport *custom = &settings->video_viewport_custom; - - vp->x = custom->x; - vp->y = custom->y; - vp->width = custom->width; - vp->height = custom->height; - } - else -#endif - { - float delta; - - if (fabsf(device_aspect - desired_aspect) < 0.0001f) - { - /* If the aspect ratios of screen and desired aspect - * ratio are sufficiently equal (floating point stuff), - * assume they are actually equal. - */ - } - else if (device_aspect > desired_aspect) - { - delta = (desired_aspect / device_aspect - 1.0f) - / 2.0f + 0.5f; - vp->x = (int)roundf(vp->full_width * (0.5f - delta)); - vp->width = (unsigned)roundf(2.0f * vp->full_width * delta); - vp->y = 0; - vp->height = vp->full_height; - } - else - { - vp->x = 0; - vp->width = vp->full_width; - delta = (device_aspect / desired_aspect - 1.0f) - / 2.0f + 0.5f; - vp->y = (int)roundf(vp->full_height * (0.5f - delta)); - vp->height = (unsigned)roundf(2.0f * vp->full_height * delta); - } - } - } - -#if defined(RARCH_MOBILE) - /* In portrait mode, we want viewport to gravitate to top of screen. */ - if (device_aspect < 1.0f) - vp->y = 0; -#endif -} - -void video_driver_show_mouse(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->show_mouse) - video_st->poke->show_mouse(video_st->data, true); -} - -void video_driver_hide_mouse(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->show_mouse) - video_st->poke->show_mouse(video_st->data, false); -} - -static void video_driver_restore_cached(settings_t *settings) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if (video_st->cached_driver_id[0]) - { - configuration_set_string(settings, - settings->arrays.video_driver, video_st->cached_driver_id); - - video_st->cached_driver_id[0] = 0; - RARCH_LOG("[Video]: Restored video driver to \"%s\".\n", - settings->arrays.video_driver); - } -} - -static bool video_driver_find_driver( - settings_t *settings, - const char *prefix, bool verbosity_enabled) -{ - int i; - video_driver_state_t *video_st = video_state_get_ptr(); - - if (video_driver_is_hw_context()) - { - struct retro_hw_render_callback *hwr = - VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st); - int rdr_major = hwr->version_major; - int rdr_minor = hwr->version_minor; - const char *rdr_context_name = hw_render_context_name(hwr->context_type, rdr_major, rdr_minor); - enum retro_hw_context_type rdr_type = hw_render_context_type(rdr_context_name); - - video_st->current_video = NULL; - - if (hwr) - { - switch (rdr_type) - { - case RETRO_HW_CONTEXT_OPENGL_CORE: - case RETRO_HW_CONTEXT_VULKAN: - case RETRO_HW_CONTEXT_DIRECT3D: -#if defined(HAVE_VULKAN) || defined(HAVE_D3D11) || defined(HAVE_D3D9) || defined(HAVE_OPENGL_CORE) - RARCH_LOG("[Video]: Using HW render, %s driver forced.\n", - rdr_context_name); - - if (!string_is_equal(settings->arrays.video_driver, - rdr_context_name)) - { - strlcpy(video_st->cached_driver_id, - settings->arrays.video_driver, - sizeof(video_st->cached_driver_id)); - configuration_set_string(settings, - settings->arrays.video_driver, - rdr_context_name); - RARCH_LOG("[Video]: \"%s\" saved as cached driver.\n", - settings->arrays.video_driver); - } - - video_st->current_video = hw_render_context_driver(rdr_type, rdr_major, rdr_minor); - return true; -#else - break; -#endif - case RETRO_HW_CONTEXT_OPENGL: -#if defined(HAVE_OPENGL) - RARCH_LOG("[Video]: Using HW render, OpenGL driver forced.\n"); - - /* If we have configured one of the HW render - * capable GL drivers, go with that. */ -#if defined(HAVE_OPENGL_CORE) - if ( !string_is_equal(settings->arrays.video_driver, "gl") && - !string_is_equal(settings->arrays.video_driver, "glcore")) - { - strlcpy(video_st->cached_driver_id, - settings->arrays.video_driver, - sizeof(video_st->cached_driver_id)); - configuration_set_string(settings, - settings->arrays.video_driver, - "glcore"); - RARCH_LOG("[Video]: \"%s\" saved as cached driver.\n", - settings->arrays.video_driver); - video_st->current_video = &video_gl_core; - return true; - } -#else - if ( !string_is_equal(settings->arrays.video_driver, "gl")) - { - strlcpy(video_st->cached_driver_id, - settings->arrays.video_driver, - sizeof(video_st->cached_driver_id)); - configuration_set_string(settings, - settings->arrays.video_driver, - "gl"); - RARCH_LOG("[Video]: \"%s\" saved as cached driver.\n", - settings->arrays.video_driver); - video_st->current_video = &video_gl2; - return true; - } -#endif - - RARCH_LOG("[Video]: Using configured \"%s\"" - " driver for GL HW render.\n", - settings->arrays.video_driver); - break; -#endif - default: - case RETRO_HW_CONTEXT_NONE: - break; - } - } - } - - if (frontend_driver_has_get_video_driver_func()) - { - if ((video_st->current_video = (video_driver_t*) - frontend_driver_get_video_driver())) - return true; - - RARCH_WARN("[Video]: Frontend supports get_video_driver() but did not specify one.\n"); - } - - i = (int)driver_find_index( - "video_driver", - settings->arrays.video_driver); - - if (i >= 0) - video_st->current_video = (video_driver_t*)video_drivers[i]; - else - { - if (verbosity_enabled) - { - unsigned d; - RARCH_ERR("Couldn't find any %s named \"%s\"\n", prefix, - settings->arrays.video_driver); - RARCH_LOG_OUTPUT("Available %ss are:\n", prefix); - for (d = 0; video_drivers[d]; d++) - RARCH_LOG_OUTPUT("\t%s\n", video_drivers[d]->ident); - RARCH_WARN("Going to default to first %s...\n", prefix); - } - - if (!(video_st->current_video = (video_driver_t*)video_drivers[0])) - return false; - } - return true; -} - -void video_driver_apply_state_changes(void) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->poke - && video_st->poke->apply_state_changes) - video_st->poke->apply_state_changes(video_st->data); -} - -bool video_driver_read_viewport(uint8_t *buffer, bool is_idle) -{ - video_driver_state_t *video_st = video_state_get_ptr(); - if ( video_st->current_video->read_viewport - && video_st->current_video->read_viewport( - video_st->data, buffer, is_idle)) - return true; - return false; -} - static void video_driver_reinit_context(struct rarch_state *p_rarch, settings_t *settings, int flags) { @@ -20726,7 +19803,7 @@ void retroarch_menu_running_finished(bool quit) struct rarch_state *p_rarch = &rarch_st; video_driver_state_t*video_st = video_state_get_ptr(); #if defined(HAVE_MENU) || defined(HAVE_OVERLAY) - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); #endif input_driver_state_t *input_st = input_state_get_ptr(); #ifdef HAVE_MENU @@ -20819,7 +19896,7 @@ static void runloop_task_msg_queue_push( struct menu_state *menu_st = menu_state_get_ptr(); #endif #ifdef HAVE_ACCESSIBILITY - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); bool accessibility_enable = settings->bools.accessibility_enable; unsigned accessibility_narrator_speech_speed = settings->uints.accessibility_narrator_speech_speed; #endif @@ -20864,8 +19941,7 @@ static void runloop_task_msg_queue_push( void retroarch_init_task_queue(void) { #ifdef HAVE_THREADS - struct rarch_state *p_rarch = &rarch_st; - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); bool threaded_enable = settings->bools.threaded_data_runloop_enable; #else bool threaded_enable = false; @@ -21196,7 +20272,7 @@ const char *retroarch_get_shader_preset(void) { #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) struct rarch_state *p_rarch = &rarch_st; - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); const char *core_name = runloop_state.system.info.library_name; bool video_shader_enable = settings->bools.video_shader_enable; unsigned video_shader_delay = settings->uints.video_shader_delay; @@ -21511,7 +20587,7 @@ void runloop_msg_queue_push(const char *msg, bool widgets_active = p_rarch->widgets_active; #endif #ifdef HAVE_ACCESSIBILITY - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); bool accessibility_enable = settings->bools.accessibility_enable; unsigned accessibility_narrator_speech_speed = settings->uints.accessibility_narrator_speech_speed; #endif @@ -22935,7 +22011,7 @@ int runloop_iterate(void) 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(); - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); unsigned video_frame_delay = settings->uints.video_frame_delay; bool vrr_runloop_enable = settings->bools.vrr_runloop_enable; unsigned max_users = settings->uints.input_max_users; @@ -23385,8 +22461,7 @@ enum retro_language rarch_get_language_from_iso(const char *iso639) void rarch_favorites_init(void) { - struct rarch_state *p_rarch = &rarch_st; - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); int content_favorites_size = settings ? settings->ints.content_favorites_size : 0; const char *path_content_favorites = settings ? settings->paths.path_content_favorites : NULL; bool playlist_sort_alphabetical = settings ? settings->bools.playlist_sort_alphabetical : false; @@ -23640,9 +22715,9 @@ bool core_set_cheat(retro_ctx_cheat_info_t *info) bool core_reset_cheat(void) { - struct rarch_state *p_rarch = &rarch_st; + struct rarch_state *p_rarch = &rarch_st; #if defined(HAVE_RUNAHEAD) && (defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)) - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); bool run_ahead_enabled = false; unsigned run_ahead_frames = 0; bool run_ahead_secondary_instance = false; @@ -24032,9 +23107,8 @@ error: bool core_options_remove_override(bool game_specific) { char new_options_path[PATH_MAX_LENGTH]; - struct rarch_state *p_rarch = &rarch_st; core_option_manager_t *coreopts = runloop_state.core_options; - settings_t *settings = p_rarch->configuration_settings; + settings_t *settings = config_get_ptr(); bool per_core_options = !settings->bools.global_core_options; const char *path_core_options = settings->paths.path_core_options; const char *current_options_path = NULL; diff --git a/retroarch_fwd_decls.h b/retroarch_fwd_decls.h index c3812452cf..2f8785bc73 100644 --- a/retroarch_fwd_decls.h +++ b/retroarch_fwd_decls.h @@ -73,11 +73,8 @@ static void ui_companion_driver_init_first( settings_t *settings, struct rarch_state *p_rarch); -static bool video_driver_find_driver( - settings_t *settings, - const char *prefix, bool verbosity_enabled); - static void driver_uninit(struct rarch_state *p_rarch, int flags); + static void drivers_init(struct rarch_state *p_rarch, settings_t *settings, int flags, @@ -117,8 +114,6 @@ static bool retroarch_apply_shader( enum rarch_shader_type type, const char *preset_path, bool message); -static void video_driver_restore_cached(settings_t *settings); - static const void *find_driver_nonempty( const char *label, int i, char *s, size_t len);