mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-26 17:50:56 +00:00
Pixel perfect integer scaling improvements (#17098)
This commit is contained in:
parent
b36d8da5d3
commit
84b58dd001
@ -520,7 +520,8 @@
|
|||||||
* Overscale rounds up instead of down, default is downscale.
|
* Overscale rounds up instead of down, default is downscale.
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_SCALE_INTEGER false
|
#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. */
|
/* Controls aspect ratio handling. */
|
||||||
|
|
||||||
|
@ -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_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_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", &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_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_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);
|
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);
|
SETTING_UINT("video_fullscreen_y", &settings->uints.video_fullscreen_y, true, DEFAULT_FULLSCREEN_Y, false);
|
||||||
#endif
|
#endif
|
||||||
SETTING_UINT("video_scale", &settings->uints.video_scale, true, DEFAULT_SCALE, false);
|
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_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);
|
SETTING_UINT("video_shader_delay", &settings->uints.video_shader_delay, true, DEFAULT_SHADER_DELAY, false);
|
||||||
#ifdef GEKKO
|
#ifdef GEKKO
|
||||||
|
@ -242,6 +242,8 @@ typedef struct settings
|
|||||||
unsigned video_fullscreen_x;
|
unsigned video_fullscreen_x;
|
||||||
unsigned video_fullscreen_y;
|
unsigned video_fullscreen_y;
|
||||||
unsigned video_scale;
|
unsigned video_scale;
|
||||||
|
unsigned video_scale_integer_axis;
|
||||||
|
unsigned video_scale_integer_scaling;
|
||||||
unsigned video_max_swapchain_images;
|
unsigned video_max_swapchain_images;
|
||||||
unsigned video_max_frame_latency;
|
unsigned video_max_frame_latency;
|
||||||
unsigned video_swap_interval;
|
unsigned video_swap_interval;
|
||||||
@ -617,7 +619,6 @@ typedef struct settings
|
|||||||
bool video_aspect_ratio_auto;
|
bool video_aspect_ratio_auto;
|
||||||
bool video_dingux_ipu_keep_aspect;
|
bool video_dingux_ipu_keep_aspect;
|
||||||
bool video_scale_integer;
|
bool video_scale_integer;
|
||||||
bool video_scale_integer_overscale;
|
|
||||||
bool video_shader_enable;
|
bool video_shader_enable;
|
||||||
bool video_shader_watch_files;
|
bool video_shader_watch_files;
|
||||||
bool video_shader_remember_last_dir;
|
bool video_shader_remember_last_dir;
|
||||||
|
@ -66,6 +66,25 @@ enum aspect_ratio
|
|||||||
ASPECT_RATIO_END
|
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
|
enum rotation
|
||||||
{
|
{
|
||||||
ORIENTATION_NORMAL = 0,
|
ORIENTATION_NORMAL = 0,
|
||||||
|
@ -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)
|
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();
|
settings_t *settings = config_get_ptr();
|
||||||
int x = 0;
|
video_driver_state_t *video_st = &video_driver_st;
|
||||||
int y = 0;
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
float viewport_bias_x = settings->floats.video_viewport_bias_x;
|
float viewport_bias_x = settings->floats.video_viewport_bias_x;
|
||||||
float viewport_bias_y = settings->floats.video_viewport_bias_y;
|
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);
|
viewport_height = (unsigned)roundf(2.0f * viewport_height * delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vp->x = x;
|
vp->x = x;
|
||||||
vp->y = y;
|
vp->y = y;
|
||||||
vp->width = viewport_width;
|
vp->width = viewport_width;
|
||||||
vp->height = viewport_height;
|
vp->height = viewport_height;
|
||||||
|
|
||||||
|
/* Statistics */
|
||||||
|
video_st->scale_width = vp->width;
|
||||||
|
video_st->scale_height = vp->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void video_driver_update_viewport(
|
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();
|
settings_t *settings = config_get_ptr();
|
||||||
video_driver_state_t *video_st = &video_driver_st;
|
video_driver_state_t *video_st = &video_driver_st;
|
||||||
unsigned video_aspect_ratio_idx = settings->uints.video_aspect_ratio_idx;
|
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_x = 0;
|
||||||
int padding_y = 0;
|
int padding_y = 0;
|
||||||
float viewport_bias_x = settings->floats.video_viewport_bias_x;
|
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)
|
if (rotation % 2)
|
||||||
content_height = content_width;
|
content_height = content_width;
|
||||||
|
|
||||||
if (content_height == 0)
|
|
||||||
content_height = 1;
|
|
||||||
|
|
||||||
/* Account for non-square pixels.
|
/* Account for non-square pixels.
|
||||||
* This is sort of contradictory with the goal of integer scale,
|
* This is sort of contradictory with the goal of integer scale,
|
||||||
* but it is desirable in some cases.
|
* 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. */
|
* system->av_info.base_height. */
|
||||||
content_width = (unsigned)roundf(content_height * aspect_ratio);
|
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)
|
if (video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
|
||||||
{
|
{
|
||||||
struct video_viewport *custom_vp = &settings->video_viewport_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)
|
if (keep_aspect)
|
||||||
{
|
{
|
||||||
/* X/Y scale must be same. */
|
int8_t half_w = 0;
|
||||||
unsigned max_scale = 1;
|
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),
|
max_scale = MIN((width / content_width) + !!(width % content_width),
|
||||||
(height / content_height) + !!(height % content_height));
|
(height / content_height) + !!(height % content_height));
|
||||||
else
|
else
|
||||||
max_scale = MIN(width / content_width,
|
max_scale = MIN(width / content_width,
|
||||||
height / content_height);
|
height / content_height);
|
||||||
|
|
||||||
padding_x = width - content_width * max_scale;
|
/* Reset both scales */
|
||||||
padding_y = height - content_height * max_scale;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -2425,9 +2551,11 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp,
|
|||||||
padding_x = width % content_width;
|
padding_x = width % content_width;
|
||||||
padding_y = height % content_height;
|
padding_y = height % content_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
width -= padding_x;
|
width -= padding_x;
|
||||||
height -= padding_y;
|
height -= padding_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
x += padding_x * viewport_bias_x;
|
x += padding_x * viewport_bias_x;
|
||||||
y += padding_y * viewport_bias_y;
|
y += padding_y * viewport_bias_y;
|
||||||
|
|
||||||
@ -2435,6 +2563,10 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp,
|
|||||||
vp->height = height;
|
vp->height = height;
|
||||||
vp->x = x;
|
vp->x = x;
|
||||||
vp->y = y;
|
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)
|
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->width = video_st->width;
|
||||||
video_info->height = video_st->height;
|
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;
|
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)
|
float scale = ((float)video_info.height / 480)
|
||||||
* 0.50f * (DEFAULT_FONT_SIZE / video_info.font_size);
|
* 0.50f * (DEFAULT_FONT_SIZE / video_info.font_size);
|
||||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||||
|
unsigned rotation = retroarch_get_rotation();
|
||||||
unsigned red = 235;
|
unsigned red = 235;
|
||||||
unsigned green = 235;
|
unsigned green = 235;
|
||||||
unsigned blue = 235;
|
unsigned blue = 235;
|
||||||
@ -3941,7 +4076,9 @@ void video_driver_frame(const void *data, unsigned width,
|
|||||||
" FPS: %3.2f\n"
|
" FPS: %3.2f\n"
|
||||||
" Sample Rate: %6.2f\n"
|
" Sample Rate: %6.2f\n"
|
||||||
"VIDEO: %s\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"
|
" Refresh: %5.2f hz\n"
|
||||||
" Frame Rate: %5.2f fps\n"
|
" Frame Rate: %5.2f fps\n"
|
||||||
" Frame Time: %5.2f ms\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_st->current_video->ident,
|
||||||
video_info.width,
|
video_info.width,
|
||||||
video_info.height,
|
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,
|
video_info.refresh_rate,
|
||||||
last_fps,
|
last_fps,
|
||||||
frame_time / 1000.0f,
|
frame_time / 1000.0f,
|
||||||
|
@ -405,6 +405,8 @@ typedef struct video_frame_info
|
|||||||
unsigned crt_switch_resolution_super;
|
unsigned crt_switch_resolution_super;
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
|
unsigned scale_width;
|
||||||
|
unsigned scale_height;
|
||||||
unsigned xmb_theme;
|
unsigned xmb_theme;
|
||||||
unsigned xmb_color_theme;
|
unsigned xmb_color_theme;
|
||||||
unsigned menu_shader_pipeline;
|
unsigned menu_shader_pipeline;
|
||||||
@ -837,6 +839,8 @@ typedef struct
|
|||||||
unsigned frame_cache_height;
|
unsigned frame_cache_height;
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
|
unsigned scale_width;
|
||||||
|
unsigned scale_height;
|
||||||
|
|
||||||
float core_hz;
|
float core_hz;
|
||||||
float aspect_ratio;
|
float aspect_ratio;
|
||||||
|
@ -2559,15 +2559,35 @@ MSG_HASH(
|
|||||||
)
|
)
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER,
|
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(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_OVERSCALE,
|
MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_AXIS,
|
||||||
"Integer Scale Overscale"
|
"Integer Scale Axis"
|
||||||
)
|
)
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_OVERSCALE,
|
MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER_AXIS,
|
||||||
"Force integer scaling to round up to the next larger integer instead of rounding down."
|
"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(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_INDEX,
|
MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_INDEX,
|
||||||
|
@ -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_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_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, 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_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_video_rotation, MENU_ENUM_SUBLABEL_VIDEO_ROTATION)
|
||||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_screen_orientation, MENU_ENUM_SUBLABEL_SCREEN_ORIENTATION)
|
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:
|
case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER:
|
||||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer);
|
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer);
|
||||||
break;
|
break;
|
||||||
case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE:
|
case MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_AXIS:
|
||||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scale_integer_overscale);
|
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;
|
break;
|
||||||
case MENU_ENUM_LABEL_PLAYLISTS_TAB:
|
case MENU_ENUM_LABEL_PLAYLISTS_TAB:
|
||||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_collection_list);
|
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_content_collection_list);
|
||||||
|
@ -9803,27 +9803,13 @@ unsigned menu_displaylist_build_list(
|
|||||||
PARSE_ONLY_BOOL, false) == 0)
|
PARSE_ONLY_BOOL, false) == 0)
|
||||||
count++;
|
count++;
|
||||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE,
|
MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_AXIS,
|
||||||
PARSE_ONLY_BOOL, false) == 0)
|
PARSE_ONLY_UINT, false) == 0)
|
||||||
count++;
|
count++;
|
||||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_X,
|
MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_SCALING,
|
||||||
PARSE_ONLY_FLOAT, false) == 0)
|
PARSE_ONLY_UINT, false) == 0)
|
||||||
count++;
|
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,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX,
|
MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX,
|
||||||
PARSE_ONLY_UINT, false) == 0)
|
PARSE_ONLY_UINT, false) == 0)
|
||||||
@ -9857,6 +9843,24 @@ unsigned menu_displaylist_build_list(
|
|||||||
default:
|
default:
|
||||||
break;
|
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,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
|
@ -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(
|
static void setting_get_string_representation_uint_playlist_show_history_icons(
|
||||||
rarch_setting_t *setting,
|
rarch_setting_t *setting,
|
||||||
char *s, size_t len)
|
char *s, size_t len)
|
||||||
@ -13579,23 +13632,41 @@ static bool setting_append_list(
|
|||||||
list_info,
|
list_info,
|
||||||
CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
|
CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
|
||||||
|
|
||||||
CONFIG_BOOL(
|
CONFIG_UINT(
|
||||||
list, list_info,
|
list, list_info,
|
||||||
&settings->bools.video_scale_integer_overscale,
|
&settings->uints.video_scale_integer_axis,
|
||||||
MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE,
|
MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_AXIS,
|
||||||
MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_OVERSCALE,
|
MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER_AXIS,
|
||||||
DEFAULT_SCALE_INTEGER_OVERSCALE,
|
DEFAULT_SCALE_INTEGER_AXIS,
|
||||||
MENU_ENUM_LABEL_VALUE_OFF,
|
|
||||||
MENU_ENUM_LABEL_VALUE_ON,
|
|
||||||
&group_info,
|
&group_info,
|
||||||
&subgroup_info,
|
&subgroup_info,
|
||||||
parent_group,
|
parent_group,
|
||||||
general_write_handler,
|
general_write_handler,
|
||||||
general_read_handler,
|
general_read_handler);
|
||||||
SD_FLAG_NONE);
|
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||||
(*list)[list_info->index - 1].action_ok = setting_bool_action_left_with_refresh;
|
(*list)[list_info->index - 1].get_string_representation =
|
||||||
(*list)[list_info->index - 1].action_left = setting_bool_action_left_with_refresh;
|
&setting_get_string_representation_uint_video_scale_integer_axis;
|
||||||
(*list)[list_info->index - 1].action_right = setting_bool_action_right_with_refresh;
|
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(
|
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(
|
||||||
list,
|
list,
|
||||||
list_info,
|
list_info,
|
||||||
|
@ -1450,7 +1450,12 @@ enum msg_hash_enums
|
|||||||
MENU_LABEL(VIDEO_NOTCH_WRITE_OVER),
|
MENU_LABEL(VIDEO_NOTCH_WRITE_OVER),
|
||||||
|
|
||||||
MENU_LABEL(VIDEO_SCALE_INTEGER),
|
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_X),
|
||||||
MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_Y),
|
MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_Y),
|
||||||
MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_WIDTH),
|
MENU_LABEL(VIDEO_VIEWPORT_CUSTOM_WIDTH),
|
||||||
|
Loading…
Reference in New Issue
Block a user