diff --git a/config.def.h b/config.def.h index 3682361dcf..423f6c05fa 100644 --- a/config.def.h +++ b/config.def.h @@ -520,7 +520,8 @@ * Overscale rounds up instead of down, default is downscale. */ #define DEFAULT_SCALE_INTEGER false -#define DEFAULT_SCALE_INTEGER_OVERSCALE false +#define DEFAULT_SCALE_INTEGER_AXIS 0 +#define DEFAULT_SCALE_INTEGER_SCALING 0 /* Controls aspect ratio handling. */ diff --git a/configuration.c b/configuration.c index a7045f7eaa..39beb2eb7e 100644 --- a/configuration.c +++ b/configuration.c @@ -1863,7 +1863,6 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("video_windowed_fullscreen", &settings->bools.video_windowed_fullscreen, true, DEFAULT_WINDOWED_FULLSCREEN, false); SETTING_BOOL("video_crop_overscan", &settings->bools.video_crop_overscan, true, DEFAULT_CROP_OVERSCAN, false); SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, DEFAULT_SCALE_INTEGER, false); - SETTING_BOOL("video_scale_integer_overscale", &settings->bools.video_scale_integer_overscale, true, DEFAULT_SCALE_INTEGER_OVERSCALE, false); SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, DEFAULT_VIDEO_SMOOTH, false); SETTING_BOOL("video_ctx_scaling", &settings->bools.video_ctx_scaling, true, DEFAULT_VIDEO_CTX_SCALING, false); SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, DEFAULT_FORCE_ASPECT, false); @@ -2456,6 +2455,8 @@ static struct config_uint_setting *populate_settings_uint( SETTING_UINT("video_fullscreen_y", &settings->uints.video_fullscreen_y, true, DEFAULT_FULLSCREEN_Y, false); #endif SETTING_UINT("video_scale", &settings->uints.video_scale, true, DEFAULT_SCALE, false); + SETTING_UINT("video_scale_integer_axis", &settings->uints.video_scale_integer_axis, true, DEFAULT_SCALE_INTEGER_AXIS, false); + SETTING_UINT("video_scale_integer_scaling", &settings->uints.video_scale_integer_scaling, true, DEFAULT_SCALE_INTEGER_SCALING, false); SETTING_UINT("video_window_opacity", &settings->uints.video_window_opacity, true, DEFAULT_WINDOW_OPACITY, false); SETTING_UINT("video_shader_delay", &settings->uints.video_shader_delay, true, DEFAULT_SHADER_DELAY, false); #ifdef GEKKO diff --git a/configuration.h b/configuration.h index 78c1de71f1..17748e956e 100644 --- a/configuration.h +++ b/configuration.h @@ -242,6 +242,8 @@ typedef struct settings unsigned video_fullscreen_x; unsigned video_fullscreen_y; unsigned video_scale; + unsigned video_scale_integer_axis; + unsigned video_scale_integer_scaling; unsigned video_max_swapchain_images; unsigned video_max_frame_latency; unsigned video_swap_interval; @@ -617,7 +619,6 @@ typedef struct settings bool video_aspect_ratio_auto; bool video_dingux_ipu_keep_aspect; bool video_scale_integer; - bool video_scale_integer_overscale; bool video_shader_enable; bool video_shader_watch_files; bool video_shader_remember_last_dir; diff --git a/gfx/video_defines.h b/gfx/video_defines.h index ceed8d18eb..4a5845b3b0 100644 --- a/gfx/video_defines.h +++ b/gfx/video_defines.h @@ -66,6 +66,25 @@ enum aspect_ratio ASPECT_RATIO_END }; +enum video_scale_integer_axis +{ + VIDEO_SCALE_INTEGER_AXIS_Y = 0, + VIDEO_SCALE_INTEGER_AXIS_Y_X, + VIDEO_SCALE_INTEGER_AXIS_Y_XHALF, + VIDEO_SCALE_INTEGER_AXIS_YHALF_XHALF, + VIDEO_SCALE_INTEGER_AXIS_X, + VIDEO_SCALE_INTEGER_AXIS_XHALF, + VIDEO_SCALE_INTEGER_AXIS_LAST +}; + +enum video_scale_integer_scaling +{ + VIDEO_SCALE_INTEGER_SCALING_UNDERSCALE = 0, + VIDEO_SCALE_INTEGER_SCALING_OVERSCALE, + VIDEO_SCALE_INTEGER_SCALING_SMART, + VIDEO_SCALE_INTEGER_SCALING_LAST +}; + enum rotation { ORIENTATION_NORMAL = 0, diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 089b86b255..12518d826f 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -2059,9 +2059,10 @@ void video_viewport_get_scaled_aspect(struct video_viewport *vp, unsigned viewpo void video_viewport_get_scaled_aspect2(struct video_viewport *vp, unsigned viewport_width, unsigned viewport_height, bool ydown, float device_aspect, float desired_aspect) { - settings_t *settings = config_get_ptr(); - int x = 0; - int y = 0; + settings_t *settings = config_get_ptr(); + video_driver_state_t *video_st = &video_driver_st; + int x = 0; + int y = 0; float viewport_bias_x = settings->floats.video_viewport_bias_x; float viewport_bias_y = settings->floats.video_viewport_bias_y; @@ -2119,10 +2120,15 @@ void video_viewport_get_scaled_aspect2(struct video_viewport *vp, unsigned viewp viewport_height = (unsigned)roundf(2.0f * viewport_height * delta); } } + vp->x = x; vp->y = y; vp->width = viewport_width; vp->height = viewport_height; + + /* Statistics */ + video_st->scale_width = vp->width; + video_st->scale_height = vp->height; } void video_driver_update_viewport( @@ -2349,7 +2355,8 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, settings_t *settings = config_get_ptr(); video_driver_state_t *video_st = &video_driver_st; unsigned video_aspect_ratio_idx = settings->uints.video_aspect_ratio_idx; - bool overscale = settings->bools.video_scale_integer_overscale; + unsigned scaling = settings->uints.video_scale_integer_scaling; + unsigned axis = settings->uints.video_scale_integer_axis; int padding_x = 0; int padding_y = 0; float viewport_bias_x = settings->floats.video_viewport_bias_x; @@ -2371,9 +2378,6 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, if (rotation % 2) content_height = content_width; - if (content_height == 0) - content_height = 1; - /* Account for non-square pixels. * This is sort of contradictory with the goal of integer scale, * but it is desirable in some cases. @@ -2382,6 +2386,12 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, * system->av_info.base_height. */ content_width = (unsigned)roundf(content_height * aspect_ratio); + if (content_width < 2 || content_height < 2) + return; + + content_width = (content_width > width) ? width : content_width; + content_height = (content_height > height) ? height : content_height; + if (video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) { struct video_viewport *custom_vp = &settings->video_viewport_custom; @@ -2406,18 +2416,134 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, { if (keep_aspect) { - /* X/Y scale must be same. */ - unsigned max_scale = 1; + int8_t half_w = 0; + int8_t half_h = 0; + uint8_t max_scale = 1; + uint8_t max_scale_w = 1; + uint8_t max_scale_h = 1; - if (overscale) + /* Overscale if less screen is lost by cropping instead of empty added by underscale */ + if (scaling == VIDEO_SCALE_INTEGER_SCALING_SMART) + { + unsigned overscale_w = (width / content_width) + !!(width % content_width); + unsigned underscale_w = (width / content_width); + unsigned overscale_h = (height / content_height) + !!(height % content_height); + unsigned underscale_h = (height / content_height); + int overscale_w_diff = (content_width * overscale_w) - width; + int underscale_w_diff = width - (content_width * underscale_w); + int overscale_h_diff = (content_height * overscale_h) - height; + int underscale_h_diff = height - (content_height * underscale_h); + int scale_h_diff = overscale_h_diff - underscale_h_diff; + + max_scale_w = underscale_w; + max_scale_h = underscale_h; + + /* Prefer nearest scale */ + if (overscale_w_diff <= underscale_w_diff) + max_scale_w = overscale_w; + + if (overscale_h_diff <= underscale_h_diff) + max_scale_h = overscale_h; + + /* Allow overscale when it is close enough */ + if (scale_h_diff > 0 && scale_h_diff < 64) + max_scale_h = overscale_h; + /* Overscale will be too much even if it is closer */ + else if ((scale_h_diff < -155 && scale_h_diff > (int)-content_height / 2) + || (scale_h_diff < -20 && scale_h_diff > -50) + || (scale_h_diff > 20)) + max_scale_h = underscale_h; + + /* Sensible limiting for small sources */ + if (content_height <= 200) + max_scale_h = underscale_h; + + max_scale = MIN(max_scale_w, max_scale_h); + } + else if (scaling == VIDEO_SCALE_INTEGER_SCALING_OVERSCALE) max_scale = MIN((width / content_width) + !!(width % content_width), (height / content_height) + !!(height % content_height)); else max_scale = MIN(width / content_width, height / content_height); - padding_x = width - content_width * max_scale; - padding_y = height - content_height * max_scale; + /* Reset both scales */ + max_scale_w = max_scale_h = max_scale; + + /* Pick the nearest width multiplier for preserving aspect ratio */ + if (axis >= VIDEO_SCALE_INTEGER_AXIS_Y_X) + { + float target_ratio = (float)content_width / (float)content_height; + float underscale_ratio = 0; + float overscale_ratio = 0; + uint16_t content_width_ar = content_width; + uint8_t overscale_w = 0; + uint8_t i = 0; + + /* Reset width to exact width */ + content_width = (rotation % 2) ? video_st->frame_cache_height : video_st->frame_cache_width; + overscale_w = (width / content_width) + !!(width % content_width); + + /* Populate the ratios */ + for (i = 1; i < overscale_w + 1; i++) + { + float scale_w_ratio = (float)(content_width * i) / (float)(content_height * max_scale_h); + + if (scale_w_ratio > target_ratio) + { + overscale_ratio = scale_w_ratio; + break; + } + underscale_ratio = scale_w_ratio; + } + + /* Pick the nearest ratio */ + if (overscale_ratio - target_ratio <= target_ratio - underscale_ratio) + max_scale_w = i; + else if (i > 1) + max_scale_w = i - 1; + + /* Special half width scale for hi-res */ + if ( axis == VIDEO_SCALE_INTEGER_AXIS_Y_XHALF + || axis == VIDEO_SCALE_INTEGER_AXIS_YHALF_XHALF + || axis == VIDEO_SCALE_INTEGER_AXIS_XHALF) + { + float scale_w_ratio = (float)(content_width * max_scale_w) / (float)(content_height * max_scale_h); + uint8_t hires_w = content_width / 512; + int content_width_diff = content_width_ar - (content_width / (hires_w + 1)); + + if ( content_width_ar - content_width_diff == (int)content_width / 2 + && content_width_diff < 20 + && scale_w_ratio - target_ratio > 0.25f + ) + half_w = -1; + } + + /* Special half height scale for hi-res */ + if (axis == VIDEO_SCALE_INTEGER_AXIS_YHALF_XHALF) + { + if ( max_scale_h == (height / content_height) + && content_height / 300 + && content_height * max_scale_h < height + ) + { + float halfstep_prev_ratio = (float)(content_width * max_scale_w) / (float)(content_height * max_scale_h); + float halfstep_next_ratio = (float)(content_width * max_scale_w) / (float)(content_height * (max_scale_h + 0.5f)); + + half_h = 1; + + if (halfstep_next_ratio - target_ratio <= target_ratio - halfstep_prev_ratio) + half_w = 1; + } + } + } + + padding_x = width - content_width * (max_scale_w + (half_w * 0.5f)); + padding_y = height - content_height * (max_scale_h + (half_h * 0.5f)); + + /* No Y padding when only touching X */ + if (axis >= VIDEO_SCALE_INTEGER_AXIS_X) + padding_y = 0; } else { @@ -2425,9 +2551,11 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, padding_x = width % content_width; padding_y = height % content_height; } + width -= padding_x; height -= padding_y; } + x += padding_x * viewport_bias_x; y += padding_y * viewport_bias_y; @@ -2435,6 +2563,10 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, vp->height = height; vp->x = x; vp->y = y; + + /* Statistics */ + video_st->scale_width = vp->width; + video_st->scale_height = vp->height; } void video_driver_display_type_set(enum rarch_display_type type) @@ -2664,6 +2796,8 @@ void video_driver_build_info(video_frame_info_t *video_info) video_info->width = video_st->width; video_info->height = video_st->height; + video_info->scale_width = video_st->scale_width; + video_info->scale_height = video_st->scale_height; video_info->hdr_enable = settings->bools.video_hdr_enable; @@ -3850,6 +3984,7 @@ void video_driver_frame(const void *data, unsigned width, float scale = ((float)video_info.height / 480) * 0.50f * (DEFAULT_FONT_SIZE / video_info.font_size); struct retro_system_av_info *av_info = &video_st->av_info; + unsigned rotation = retroarch_get_rotation(); unsigned red = 235; unsigned green = 235; unsigned blue = 235; @@ -3941,7 +4076,9 @@ void video_driver_frame(const void *data, unsigned width, " FPS: %3.2f\n" " Sample Rate: %6.2f\n" "VIDEO: %s\n" - " Viewport: %d x %d\n" + " Viewport: %u x %u\n" + " - Scale: %u x %u\n" + " - Scale X/Y: %2.2f / %2.2f\n" " Refresh: %5.2f hz\n" " Frame Rate: %5.2f fps\n" " Frame Time: %5.2f ms\n" @@ -3967,6 +4104,10 @@ void video_driver_frame(const void *data, unsigned width, video_st->current_video->ident, video_info.width, video_info.height, + video_info.scale_width, + video_info.scale_height, + (float)video_info.scale_width / ((rotation % 2) ? (float)video_st->frame_cache_height : (float)video_st->frame_cache_width), + (float)video_info.scale_height / ((rotation % 2) ? (float)video_st->frame_cache_width : (float)video_st->frame_cache_height), video_info.refresh_rate, last_fps, frame_time / 1000.0f, diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 166bccab49..2e87a17f2e 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -405,6 +405,8 @@ typedef struct video_frame_info unsigned crt_switch_resolution_super; unsigned width; unsigned height; + unsigned scale_width; + unsigned scale_height; unsigned xmb_theme; unsigned xmb_color_theme; unsigned menu_shader_pipeline; @@ -837,6 +839,8 @@ typedef struct unsigned frame_cache_height; unsigned width; unsigned height; + unsigned scale_width; + unsigned scale_height; float core_hz; float aspect_ratio; diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 55eab30e99..10aaa7d8cb 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2559,15 +2559,35 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER, - "Scale video in integer steps only. The base size depends on system-reported geometry and aspect ratio. If 'Force Aspect Ratio' is not set, X/Y will be integer scaled independently." + "Scale video in integer steps only. The base size depends on core-reported geometry and aspect ratio." ) MSG_HASH( - MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_OVERSCALE, - "Integer Scale Overscale" + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_AXIS, + "Integer Scale Axis" ) MSG_HASH( - MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_OVERSCALE, - "Force integer scaling to round up to the next larger integer instead of rounding down." + MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_AXIS, + "Scale only height, or both height and width. Half steps apply to high resolution sources." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING, + "Integer Scale Scaling" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_SCALING, + "Round down or up to the next integer. 'Smart' drops to underscale when image is cropped too much." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_UNDERSCALE, + "Underscale" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_OVERSCALE, + "Overscale" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_SMART, + "Smart" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_INDEX, diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 5f199b1db8..9a465b1e37 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -720,7 +720,8 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_overlay_dpad_diag_sens, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_overlay_abxy_diag_sens, MENU_ENUM_SUBLABEL_INPUT_OVERLAY_ABXY_DIAGONAL_SENSITIVITY) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_content_collection_list, MENU_ENUM_SUBLABEL_PLAYLISTS_TAB) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_scale_integer, MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER) -DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_scale_integer_overscale, MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_OVERSCALE) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_scale_integer_axis, MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_AXIS) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_scale_integer_scaling, MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_SCALING) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_gpu_screenshot, MENU_ENUM_SUBLABEL_VIDEO_GPU_SCREENSHOT) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_rotation, MENU_ENUM_SUBLABEL_VIDEO_ROTATION) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_screen_orientation, MENU_ENUM_SUBLABEL_SCREEN_ORIENTATION) @@ -4243,8 +4244,11 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer); break; - case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE: - BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer_overscale); + case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_AXIS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer_axis); + break; + case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_SCALING: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer_scaling); break; case MENU_ENUM_LABEL_PLAYLISTS_TAB: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_collection_list); diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 237537d943..53de761247 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -9803,27 +9803,13 @@ unsigned menu_displaylist_build_list( PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE, - PARSE_ONLY_BOOL, false) == 0) + MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_AXIS, + PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_X, - PARSE_ONLY_FLOAT, false) == 0) + MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_SCALING, + PARSE_ONLY_UINT, false) == 0) count++; - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_Y, - PARSE_ONLY_FLOAT, false) == 0) - count++; -#if defined(RARCH_MOBILE) - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_PORTRAIT_X, - PARSE_ONLY_FLOAT, false) == 0) - count++; - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_PORTRAIT_Y, - PARSE_ONLY_FLOAT, false) == 0) - count++; -#endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX, PARSE_ONLY_UINT, false) == 0) @@ -9857,6 +9843,24 @@ unsigned menu_displaylist_build_list( default: break; } + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_X, + PARSE_ONLY_FLOAT, false) == 0) + count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_Y, + PARSE_ONLY_FLOAT, false) == 0) + count++; +#if defined(RARCH_MOBILE) + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_PORTRAIT_X, + PARSE_ONLY_FLOAT, false) == 0) + count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_PORTRAIT_Y, + PARSE_ONLY_FLOAT, false) == 0) + count++; +#endif } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index a4bb61bb09..54d532bd85 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -7346,6 +7346,59 @@ static void setting_get_string_representation_uint_quit_on_close_content( } } +static void setting_get_string_representation_uint_video_scale_integer_axis( + rarch_setting_t *setting, + char *s, size_t len) +{ + if (!setting) + return; + + switch (*setting->value.target.unsigned_integer) + { + default: + case VIDEO_SCALE_INTEGER_AXIS_Y: + strlcpy(s, "Y", len); + break; + case VIDEO_SCALE_INTEGER_AXIS_Y_X: + strlcpy(s, "Y + X", len); + break; + case VIDEO_SCALE_INTEGER_AXIS_Y_XHALF: + strlcpy(s, "Y + X.5", len); + break; + case VIDEO_SCALE_INTEGER_AXIS_YHALF_XHALF: + strlcpy(s, "Y.5 + X.5", len); + break; + case VIDEO_SCALE_INTEGER_AXIS_X: + strlcpy(s, "X", len); + break; + case VIDEO_SCALE_INTEGER_AXIS_XHALF: + strlcpy(s, "X.5", len); + break; + } +} + +static void setting_get_string_representation_uint_video_scale_integer_scaling( + rarch_setting_t *setting, + char *s, size_t len) +{ + if (!setting) + return; + + switch (*setting->value.target.unsigned_integer) + { + default: + case VIDEO_SCALE_INTEGER_SCALING_UNDERSCALE: + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_UNDERSCALE), len); + break; + case VIDEO_SCALE_INTEGER_SCALING_OVERSCALE: + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_OVERSCALE), len); + break; + case VIDEO_SCALE_INTEGER_SCALING_SMART: + strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_SMART), len); + break; + } +} + static void setting_get_string_representation_uint_playlist_show_history_icons( rarch_setting_t *setting, char *s, size_t len) @@ -13579,23 +13632,41 @@ static bool setting_append_list( list_info, CMD_EVENT_VIDEO_APPLY_STATE_CHANGES); - CONFIG_BOOL( + CONFIG_UINT( list, list_info, - &settings->bools.video_scale_integer_overscale, - MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE, - MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_OVERSCALE, - DEFAULT_SCALE_INTEGER_OVERSCALE, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, + &settings->uints.video_scale_integer_axis, + MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_AXIS, + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_AXIS, + DEFAULT_SCALE_INTEGER_AXIS, &group_info, &subgroup_info, parent_group, general_write_handler, - general_read_handler, - SD_FLAG_NONE); - (*list)[list_info->index - 1].action_ok = setting_bool_action_left_with_refresh; - (*list)[list_info->index - 1].action_left = setting_bool_action_left_with_refresh; - (*list)[list_info->index - 1].action_right = setting_bool_action_right_with_refresh; + 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_video_scale_integer_axis; + menu_settings_list_current_add_range(list, list_info, 0, VIDEO_SCALE_INTEGER_AXIS_LAST - 1, 1, true, true); + MENU_SETTINGS_LIST_CURRENT_ADD_CMD( + list, + list_info, + CMD_EVENT_VIDEO_APPLY_STATE_CHANGES); + + CONFIG_UINT( + list, list_info, + &settings->uints.video_scale_integer_scaling, + MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_SCALING, + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING, + DEFAULT_SCALE_INTEGER_SCALING, + &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_video_scale_integer_scaling; + menu_settings_list_current_add_range(list, list_info, 0, VIDEO_SCALE_INTEGER_SCALING_LAST - 1, 1, true, true); MENU_SETTINGS_LIST_CURRENT_ADD_CMD( list, list_info, diff --git a/msg_hash.h b/msg_hash.h index a72f0046fb..0915739740 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1450,7 +1450,12 @@ enum msg_hash_enums MENU_LABEL(VIDEO_NOTCH_WRITE_OVER), MENU_LABEL(VIDEO_SCALE_INTEGER), - MENU_LABEL(VIDEO_SCALE_INTEGER_OVERSCALE), + MENU_LABEL(VIDEO_SCALE_INTEGER_AXIS), + MENU_LABEL(VIDEO_SCALE_INTEGER_SCALING), + MENU_LABEL(VIDEO_SCALE_INTEGER_OVERSCALE), /* deprecated */ + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_UNDERSCALE, + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_OVERSCALE, + MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_SCALING_SMART, MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_X), MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_Y), MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_WIDTH),