mirror of
https://github.com/libretro/RetroArch
synced 2025-03-02 19:13:34 +00:00
(RGUI) Add optional internal upscaling
This commit is contained in:
parent
eb1dc6624f
commit
cf6e23cebd
@ -379,6 +379,8 @@ static unsigned rgui_thumbnail_downscaler = RGUI_THUMB_SCALE_POINT;
|
||||
|
||||
static bool rgui_lock_aspect = false;
|
||||
|
||||
static unsigned rgui_internal_upscale_level = RGUI_UPSCALE_NONE;
|
||||
|
||||
#else
|
||||
static bool default_block_config_read = false;
|
||||
static bool automatically_add_content_to_playlist = false;
|
||||
|
@ -1669,6 +1669,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
#ifdef HAVE_RGUI
|
||||
SETTING_UINT("rgui_menu_color_theme", &settings->uints.menu_rgui_color_theme, true, rgui_color_theme, false);
|
||||
SETTING_UINT("rgui_thumbnail_downscaler", &settings->uints.menu_rgui_thumbnail_downscaler, true, rgui_thumbnail_downscaler, false);
|
||||
SETTING_UINT("rgui_internal_upscale_level", &settings->uints.menu_rgui_internal_upscale_level, true, rgui_internal_upscale_level, false);
|
||||
#endif
|
||||
#ifdef HAVE_LIBNX
|
||||
SETTING_UINT("split_joycon_p1", &settings->uints.input_split_joycon[0], true, 0, false);
|
||||
|
@ -426,6 +426,7 @@ typedef struct settings
|
||||
unsigned menu_font_color_red;
|
||||
unsigned menu_font_color_green;
|
||||
unsigned menu_font_color_blue;
|
||||
unsigned menu_rgui_internal_upscale_level;
|
||||
|
||||
unsigned camera_width;
|
||||
unsigned camera_height;
|
||||
|
@ -1595,6 +1595,8 @@ MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE,
|
||||
"menu_rgui_background_filler_thickness_enable")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_LOCK_ASPECT,
|
||||
"menu_rgui_lock_aspect")
|
||||
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
|
||||
"rgui_internal_upscale_level")
|
||||
MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_REWIND,
|
||||
"menu_show_rewind_settings")
|
||||
MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY,
|
||||
|
@ -2970,6 +2970,46 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC,
|
||||
"Sinc/Lanczos3 (Slow)"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_NONE,
|
||||
"None"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_AUTO,
|
||||
"Auto"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X2,
|
||||
"x2"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X3,
|
||||
"x3"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X4,
|
||||
"x4"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X5,
|
||||
"x5"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X6,
|
||||
"x6"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X7,
|
||||
"x7"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X8,
|
||||
"x8"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X9,
|
||||
"x9"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY,
|
||||
"Thumbnails"
|
||||
@ -6692,6 +6732,14 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MENU_RGUI_LOCK_ASPECT,
|
||||
"Ensures that the menu is always displayed with the correct aspect ratio. If disabled, the quick menu will be stretched to match the currently loaded content."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
|
||||
"Internal Upscaling"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
|
||||
"Upscale menu interface before drawing to screen. When used with 'Menu Linear Filter' enabled, removes scaling artefacts (uneven pixels) while maintaining a sharp image. Has a significant performance impact that increases with upscaling level."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION,
|
||||
"For CRT displays only. Attempts to use exact core/game resolution and refresh rate."
|
||||
|
@ -517,6 +517,7 @@ default_sublabel_macro(action_bind_sublabel_rgui_menu_color_theme,
|
||||
default_sublabel_macro(action_bind_sublabel_rgui_menu_theme_preset, MENU_ENUM_SUBLABEL_RGUI_MENU_THEME_PRESET)
|
||||
default_sublabel_macro(action_bind_sublabel_menu_rgui_thumbnail_downscaler, MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER)
|
||||
default_sublabel_macro(action_bind_sublabel_content_runtime_log, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG)
|
||||
default_sublabel_macro(action_bind_sublabel_menu_rgui_internal_upscale_level, MENU_ENUM_SUBLABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL)
|
||||
|
||||
static int action_bind_sublabel_systeminfo_controller_entry(
|
||||
file_list_t *list,
|
||||
@ -2252,6 +2253,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_internal_upscale_level);
|
||||
break;
|
||||
default:
|
||||
case MSG_UNKNOWN:
|
||||
return -1;
|
||||
|
@ -469,6 +469,19 @@ static wallpaper_t wallpaper = {
|
||||
{0}
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
uint16_t *data;
|
||||
} upscale_buf_t;
|
||||
|
||||
static upscale_buf_t upscale_buf = {
|
||||
0,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
|
||||
static uint16_t *rgui_framebuf_data = NULL;
|
||||
|
||||
#if defined(PS2)
|
||||
@ -1927,12 +1940,19 @@ static void rgui_free(void *data)
|
||||
|
||||
if (!string_is_empty(wallpaper.path))
|
||||
free(wallpaper.path);
|
||||
|
||||
if (upscale_buf.data)
|
||||
{
|
||||
free(upscale_buf.data);
|
||||
upscale_buf.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void rgui_set_texture(void)
|
||||
{
|
||||
size_t fb_pitch;
|
||||
unsigned fb_width, fb_height;
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (!menu_display_get_framebuffer_dirty_flag())
|
||||
return;
|
||||
@ -1942,8 +1962,90 @@ static void rgui_set_texture(void)
|
||||
|
||||
menu_display_unset_framebuffer_dirty_flag();
|
||||
|
||||
video_driver_set_texture_frame(rgui_framebuf_data,
|
||||
if (settings->uints.menu_rgui_internal_upscale_level == RGUI_UPSCALE_NONE)
|
||||
{
|
||||
video_driver_set_texture_frame(rgui_framebuf_data,
|
||||
false, fb_width, fb_height, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get viewport dimensions */
|
||||
struct video_viewport vp;
|
||||
video_driver_get_viewport_info(&vp);
|
||||
|
||||
/* If viewport is currently the same size (or smaller)
|
||||
* than the menu framebuffer, no scaling is required */
|
||||
if ((vp.width <= fb_width) && (vp.height <= fb_height))
|
||||
{
|
||||
video_driver_set_texture_frame(rgui_framebuf_data,
|
||||
false, fb_width, fb_height, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned out_width;
|
||||
unsigned out_height;
|
||||
uint32_t x_ratio, y_ratio;
|
||||
unsigned x_src, y_src;
|
||||
unsigned x_dst, y_dst;
|
||||
|
||||
/* Determine output size */
|
||||
if (settings->uints.menu_rgui_internal_upscale_level == RGUI_UPSCALE_AUTO)
|
||||
{
|
||||
out_width = ((vp.width / fb_width) + 1) * fb_width;
|
||||
out_height = ((vp.height / fb_height) + 1) * fb_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_width = settings->uints.menu_rgui_internal_upscale_level * fb_width;
|
||||
out_height = settings->uints.menu_rgui_internal_upscale_level * fb_height;
|
||||
}
|
||||
|
||||
/* Allocate upscaling buffer, if required */
|
||||
if ((upscale_buf.width != out_width) || (upscale_buf.height != out_height) || !upscale_buf.data)
|
||||
{
|
||||
upscale_buf.width = out_width;
|
||||
upscale_buf.height = out_height;
|
||||
|
||||
if (upscale_buf.data)
|
||||
{
|
||||
free(upscale_buf.data);
|
||||
upscale_buf.data = NULL;
|
||||
}
|
||||
|
||||
upscale_buf.data = (uint16_t*)calloc(out_width * out_height, sizeof(uint16_t));
|
||||
if (!upscale_buf.data)
|
||||
{
|
||||
/* Uh oh... This could mean we don't have enough
|
||||
* memory, so disable upscaling and draw the usual
|
||||
* framebuffer... */
|
||||
settings->uints.menu_rgui_internal_upscale_level = RGUI_UPSCALE_NONE;
|
||||
video_driver_set_texture_frame(rgui_framebuf_data,
|
||||
false, fb_width, fb_height, 1.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform nearest neighbour upscaling
|
||||
* NB: We're duplicating code here, but trying to handle
|
||||
* this with a polymorphic function is too much of a drag... */
|
||||
x_ratio = ((fb_width << 16) / out_width);
|
||||
y_ratio = ((fb_height << 16) / out_height);
|
||||
|
||||
for (y_dst = 0; y_dst < out_height; y_dst++)
|
||||
{
|
||||
y_src = (y_dst * y_ratio) >> 16;
|
||||
for (x_dst = 0; x_dst < out_width; x_dst++)
|
||||
{
|
||||
x_src = (x_dst * x_ratio) >> 16;
|
||||
upscale_buf.data[(y_dst * out_width) + x_dst] = rgui_framebuf_data[(y_src * fb_width) + x_src];
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw upscaled texture */
|
||||
video_driver_set_texture_frame(upscale_buf.data,
|
||||
false, out_width, out_height, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rgui_navigation_clear(void *data, bool pending_push)
|
||||
@ -2300,6 +2402,15 @@ static void rgui_toggle(void *userdata, bool menu_on)
|
||||
video_driver_set_aspect_ratio();
|
||||
}
|
||||
}
|
||||
|
||||
/* Upscaling buffer is only required while menu is on. Save
|
||||
* memory by freeing it whenever we switch back to the current
|
||||
* content */
|
||||
if (!menu_on && upscale_buf.data)
|
||||
{
|
||||
free(upscale_buf.data);
|
||||
upscale_buf.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
menu_ctx_driver_t menu_ctx_rgui = {
|
||||
|
@ -233,6 +233,21 @@ enum rgui_thumbnail_scaler
|
||||
RGUI_THUMB_SCALE_LAST
|
||||
};
|
||||
|
||||
enum rgui_upscale_level
|
||||
{
|
||||
RGUI_UPSCALE_NONE = 0,
|
||||
RGUI_UPSCALE_AUTO,
|
||||
RGUI_UPSCALE_X2,
|
||||
RGUI_UPSCALE_X3,
|
||||
RGUI_UPSCALE_X4,
|
||||
RGUI_UPSCALE_X5,
|
||||
RGUI_UPSCALE_X6,
|
||||
RGUI_UPSCALE_X7,
|
||||
RGUI_UPSCALE_X8,
|
||||
RGUI_UPSCALE_X9, /* All the way to 4k */
|
||||
RGUI_UPSCALE_LAST
|
||||
};
|
||||
|
||||
enum menu_action
|
||||
{
|
||||
MENU_ACTION_NOOP = 0,
|
||||
|
@ -6020,6 +6020,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
|
||||
MENU_ENUM_LABEL_MENU_LINEAR_FILTER,
|
||||
PARSE_ONLY_BOOL, false) == 0)
|
||||
count++;
|
||||
if (menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
|
||||
PARSE_ONLY_UINT, false) == 0)
|
||||
count++;
|
||||
if (menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_MENU_RGUI_LOCK_ASPECT,
|
||||
PARSE_ONLY_BOOL, false) == 0)
|
||||
|
@ -819,6 +819,78 @@ static void setting_get_string_representation_uint_rgui_thumbnail_scaler(
|
||||
}
|
||||
}
|
||||
|
||||
static void setting_get_string_representation_uint_rgui_internal_upscale_level(
|
||||
rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (!setting)
|
||||
return;
|
||||
|
||||
switch (*setting->value.target.unsigned_integer)
|
||||
{
|
||||
case RGUI_UPSCALE_NONE:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_NONE),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_AUTO:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_AUTO),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X2:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X2),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X3:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X3),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X4:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X4),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X5:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X5),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X6:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X6),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X7:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X7),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X8:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X8),
|
||||
len);
|
||||
break;
|
||||
case RGUI_UPSCALE_X9:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X9),
|
||||
len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_XMB
|
||||
static void setting_get_string_representation_uint_xmb_icon_theme(
|
||||
rarch_setting_t *setting,
|
||||
@ -7990,6 +8062,7 @@ static bool setting_append_list(
|
||||
);
|
||||
|
||||
if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING))
|
||||
{
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.menu_linear_filter,
|
||||
@ -8006,6 +8079,24 @@ static bool setting_append_list(
|
||||
SD_FLAG_NONE
|
||||
);
|
||||
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.menu_rgui_internal_upscale_level,
|
||||
MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
|
||||
MENU_ENUM_LABEL_VALUE_MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
|
||||
rgui_internal_upscale_level,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
(*list)[list_info->index - 1].get_string_representation =
|
||||
&setting_get_string_representation_uint_rgui_internal_upscale_level;
|
||||
menu_settings_list_current_add_range(list, list_info, 0, RGUI_UPSCALE_LAST-1, 1, true, true);
|
||||
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED);
|
||||
}
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.menu_rgui_lock_aspect,
|
||||
|
12
msg_hash.h
12
msg_hash.h
@ -858,6 +858,7 @@ enum msg_hash_enums
|
||||
MENU_LABEL(MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE),
|
||||
MENU_LABEL(MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE),
|
||||
MENU_LABEL(MENU_RGUI_LOCK_ASPECT),
|
||||
MENU_LABEL(MENU_RGUI_INTERNAL_UPSCALE_LEVEL),
|
||||
MENU_LABEL(MENU_LINEAR_FILTER),
|
||||
MENU_LABEL(MENU_HORIZONTAL_ANIMATION),
|
||||
MENU_LABEL(NAVIGATION_WRAPAROUND),
|
||||
@ -1956,6 +1957,17 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_BILINEAR,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC,
|
||||
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_AUTO,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X2,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X3,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X4,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X5,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X6,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X7,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X8,
|
||||
MENU_ENUM_LABEL_VALUE_RGUI_UPSCALE_X9,
|
||||
|
||||
/* Callback strings */
|
||||
MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST,
|
||||
MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD,
|
||||
|
Loading…
x
Reference in New Issue
Block a user