(RGUI) Add optional internal upscaling

This commit is contained in:
jdgleaver 2019-02-13 11:02:15 +00:00
parent eb1dc6624f
commit cf6e23cebd
11 changed files with 292 additions and 1 deletions

View File

@ -379,6 +379,8 @@ static unsigned rgui_thumbnail_downscaler = RGUI_THUMB_SCALE_POINT;
static bool rgui_lock_aspect = false; static bool rgui_lock_aspect = false;
static unsigned rgui_internal_upscale_level = RGUI_UPSCALE_NONE;
#else #else
static bool default_block_config_read = false; static bool default_block_config_read = false;
static bool automatically_add_content_to_playlist = false; static bool automatically_add_content_to_playlist = false;

View File

@ -1669,6 +1669,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
#ifdef HAVE_RGUI #ifdef HAVE_RGUI
SETTING_UINT("rgui_menu_color_theme", &settings->uints.menu_rgui_color_theme, true, rgui_color_theme, false); 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_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 #endif
#ifdef HAVE_LIBNX #ifdef HAVE_LIBNX
SETTING_UINT("split_joycon_p1", &settings->uints.input_split_joycon[0], true, 0, false); SETTING_UINT("split_joycon_p1", &settings->uints.input_split_joycon[0], true, 0, false);

View File

@ -426,6 +426,7 @@ typedef struct settings
unsigned menu_font_color_red; unsigned menu_font_color_red;
unsigned menu_font_color_green; unsigned menu_font_color_green;
unsigned menu_font_color_blue; unsigned menu_font_color_blue;
unsigned menu_rgui_internal_upscale_level;
unsigned camera_width; unsigned camera_width;
unsigned camera_height; unsigned camera_height;

View File

@ -1595,6 +1595,8 @@ MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE,
"menu_rgui_background_filler_thickness_enable") "menu_rgui_background_filler_thickness_enable")
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_LOCK_ASPECT, MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_LOCK_ASPECT,
"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, MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_REWIND,
"menu_show_rewind_settings") "menu_show_rewind_settings")
MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY, MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY,

View File

@ -2970,6 +2970,46 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC, MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC,
"Sinc/Lanczos3 (Slow)" "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( MSG_HASH(
MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY, MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY,
"Thumbnails" "Thumbnails"
@ -6692,6 +6732,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_MENU_RGUI_LOCK_ASPECT, 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." "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( MSG_HASH(
MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION,
"For CRT displays only. Attempts to use exact core/game resolution and refresh rate." "For CRT displays only. Attempts to use exact core/game resolution and refresh rate."

View File

@ -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_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_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_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( static int action_bind_sublabel_systeminfo_controller_entry(
file_list_t *list, 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: case MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_runtime_log);
break; break;
case MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_internal_upscale_level);
break;
default: default:
case MSG_UNKNOWN: case MSG_UNKNOWN:
return -1; return -1;

View File

@ -469,6 +469,19 @@ static wallpaper_t wallpaper = {
{0} {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; static uint16_t *rgui_framebuf_data = NULL;
#if defined(PS2) #if defined(PS2)
@ -1927,12 +1940,19 @@ static void rgui_free(void *data)
if (!string_is_empty(wallpaper.path)) if (!string_is_empty(wallpaper.path))
free(wallpaper.path); free(wallpaper.path);
if (upscale_buf.data)
{
free(upscale_buf.data);
upscale_buf.data = NULL;
}
} }
static void rgui_set_texture(void) static void rgui_set_texture(void)
{ {
size_t fb_pitch; size_t fb_pitch;
unsigned fb_width, fb_height; unsigned fb_width, fb_height;
settings_t *settings = config_get_ptr();
if (!menu_display_get_framebuffer_dirty_flag()) if (!menu_display_get_framebuffer_dirty_flag())
return; return;
@ -1942,8 +1962,90 @@ static void rgui_set_texture(void)
menu_display_unset_framebuffer_dirty_flag(); 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); 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) 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(); 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 = { menu_ctx_driver_t menu_ctx_rgui = {

View File

@ -233,6 +233,21 @@ enum rgui_thumbnail_scaler
RGUI_THUMB_SCALE_LAST 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 enum menu_action
{ {
MENU_ACTION_NOOP = 0, MENU_ACTION_NOOP = 0,

View File

@ -6020,6 +6020,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
MENU_ENUM_LABEL_MENU_LINEAR_FILTER, MENU_ENUM_LABEL_MENU_LINEAR_FILTER,
PARSE_ONLY_BOOL, false) == 0) PARSE_ONLY_BOOL, false) == 0)
count++; 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, if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MENU_RGUI_LOCK_ASPECT, MENU_ENUM_LABEL_MENU_RGUI_LOCK_ASPECT,
PARSE_ONLY_BOOL, false) == 0) PARSE_ONLY_BOOL, false) == 0)

View File

@ -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 #ifdef HAVE_XMB
static void setting_get_string_representation_uint_xmb_icon_theme( static void setting_get_string_representation_uint_xmb_icon_theme(
rarch_setting_t *setting, 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)) if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING))
{
CONFIG_BOOL( CONFIG_BOOL(
list, list_info, list, list_info,
&settings->bools.menu_linear_filter, &settings->bools.menu_linear_filter,
@ -8006,6 +8079,24 @@ static bool setting_append_list(
SD_FLAG_NONE 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( CONFIG_BOOL(
list, list_info, list, list_info,
&settings->bools.menu_rgui_lock_aspect, &settings->bools.menu_rgui_lock_aspect,

View File

@ -858,6 +858,7 @@ enum msg_hash_enums
MENU_LABEL(MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE), MENU_LABEL(MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE),
MENU_LABEL(MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE), MENU_LABEL(MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE),
MENU_LABEL(MENU_RGUI_LOCK_ASPECT), MENU_LABEL(MENU_RGUI_LOCK_ASPECT),
MENU_LABEL(MENU_RGUI_INTERNAL_UPSCALE_LEVEL),
MENU_LABEL(MENU_LINEAR_FILTER), MENU_LABEL(MENU_LINEAR_FILTER),
MENU_LABEL(MENU_HORIZONTAL_ANIMATION), MENU_LABEL(MENU_HORIZONTAL_ANIMATION),
MENU_LABEL(NAVIGATION_WRAPAROUND), 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_BILINEAR,
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_SINC, 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 */ /* Callback strings */
MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST, MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST,
MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD, MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD,