From 61707d2783bfc30aa18e81232251c58f428bbc8d Mon Sep 17 00:00:00 2001 From: Themaister Date: Tue, 29 Jan 2013 19:28:33 +0100 Subject: [PATCH] Add integer scale options. --- config.def.h | 5 +++++ general.h | 1 + gfx/gfx_common.c | 38 ++++++++++++++++++++++++++++++++++++++ gfx/gfx_common.h | 4 ++++ gfx/gl.c | 26 ++++++++++++++++++-------- gfx/xvideo.c | 8 +++++++- retroarch.cfg | 5 +++++ settings.c | 2 ++ 8 files changed, 80 insertions(+), 9 deletions(-) diff --git a/config.def.h b/config.def.h index 36877ef2af..bf56067660 100644 --- a/config.def.h +++ b/config.def.h @@ -224,6 +224,11 @@ static const bool video_smooth = true; // On resize and fullscreen, rendering area will stay 4:3 static const bool force_aspect = true; +// Only scale in integer steps. +// The base size depends on system-reported geometry and aspect ratio. +// If video_force_aspect is not set, X/Y will be integer scaled independently. +static const bool scale_integer = false; + // Controls aspect ratio handling. static const float aspect_ratio = DEFAULT_ASPECT_RATIO; // Automatic static const bool aspect_ratio_auto = false; // 1:1 PAR diff --git a/general.h b/general.h index 543bfc8c91..8606266f7e 100644 --- a/general.h +++ b/general.h @@ -157,6 +157,7 @@ struct settings bool crop_overscan; float aspect_ratio; bool aspect_ratio_auto; + bool scale_integer; unsigned aspect_ratio_idx; char cg_shader_path[PATH_MAX]; char bsnes_shader_path[PATH_MAX]; diff --git a/gfx/gfx_common.c b/gfx/gfx_common.c index e09056d7e0..a98a7ab376 100644 --- a/gfx/gfx_common.c +++ b/gfx/gfx_common.c @@ -176,3 +176,41 @@ void gfx_set_dwm(void) } #endif +void gfx_scale_integer(struct rarch_viewport *vp, unsigned width, unsigned height, float aspect_ratio, bool keep_aspect) +{ + // Use system reported sizes as these define the geometry for the "normal" case. + unsigned base_height = g_extern.system.av_info.geometry.base_height; + // Account for non-square pixels. + // This is sort of contradictory with the goal of integer scale, + // but it is desirable in some cases. + // If square pixels are used, base_height will be equal to g_extern.system.av_info.base_height. + unsigned base_width = (unsigned)roundf(base_height * aspect_ratio); + + unsigned padding_x = 0; + unsigned padding_y = 0; + + // Make sure that we don't get 0x scale ... + if (width >= base_width && height >= base_height) + { + if (keep_aspect) // X/Y scale must be same. + { + unsigned max_scale = min(width / base_width, height / base_height); + padding_x = width - base_width * max_scale; + padding_y = height - base_height * max_scale; + } + else // X/Y can be independent, each scaled as much as possible. + { + padding_x = width % base_width; + padding_y = height % base_height; + } + } + + width -= padding_x; + height -= padding_y; + + vp->width = width; + vp->height = height; + vp->x = padding_x >> 1; + vp->y = padding_y >> 1; +} + diff --git a/gfx/gfx_common.h b/gfx/gfx_common.h index 463b39df64..90124617f8 100644 --- a/gfx/gfx_common.h +++ b/gfx/gfx_common.h @@ -21,6 +21,7 @@ extern "C" { #endif #include +#include "../general.h" #include "../boolean.h" #ifdef HAVE_CONFIG_H @@ -36,6 +37,9 @@ void gfx_window_title_reset(void); void gfx_set_dwm(void); #endif +void gfx_scale_integer(struct rarch_viewport *vp, unsigned win_width, unsigned win_height, + float aspect_ratio, bool keep_aspect); + #ifdef __cplusplus } #endif diff --git a/gfx/gl.c b/gfx/gl.c index e0fd0b28f0..097f58d044 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -674,7 +674,11 @@ void gl_set_viewport(void *data, unsigned width, unsigned height, bool force_ful else device_aspect = (float)width / height; - if (gl->keep_aspect && !force_full) + if (g_settings.video.scale_integer && !force_full) + { + gfx_scale_integer(&gl->vp, width, height, g_settings.video.aspect_ratio, gl->keep_aspect); + } + else if (gl->keep_aspect && !force_full) { float desired_aspect = g_settings.video.aspect_ratio; float delta; @@ -708,20 +712,26 @@ void gl_set_viewport(void *data, unsigned width, unsigned height, bool force_ful height = (unsigned)(2.0 * height * delta); } } + + gl->vp.x = x; + gl->vp.y = y; + gl->vp.width = width; + gl->vp.height = height; + } + else + { + gl->vp.x = gl->vp.y = 0; + gl->vp.width = width; + gl->vp.height = height; } #ifdef ANDROID // In portrait mode, we want viewport to gravitate to top of screen. if (device_aspect < 1.0f) - y *= 2; + gl->vp.y *= 2; #endif - glViewport(x, y, width, height); - gl->vp.x = x; - gl->vp.y = y; - gl->vp.width = width; - gl->vp.height = height; - + glViewport(gl->vp.x, gl->vp.y, gl->vp.width, gl->vp.height); gl_set_projection(gl, &ortho, allow_rotate); // Set last backbuffer viewport. diff --git a/gfx/xvideo.c b/gfx/xvideo.c index c825bf1b86..a4db814332 100644 --- a/gfx/xvideo.c +++ b/gfx/xvideo.c @@ -533,7 +533,11 @@ static void calc_out_rect(bool keep_aspect, struct rarch_viewport *vp, unsigned vp->full_width = vp_width; vp->full_height = vp_height; - if (!keep_aspect) + if (g_settings.video.scale_integer) + { + gfx_scale_integer(vp, vp_width, vp_height, g_settings.video.aspect_ratio, keep_aspect); + } + else if (!keep_aspect) { vp->x = 0; vp->y = 0; vp->width = vp_width; @@ -679,6 +683,8 @@ static bool xv_frame(void *data, const void *frame, unsigned width, unsigned hei xv->render_func(xv, frame, width, height, pitch); calc_out_rect(xv->keep_aspect, &xv->vp, target.width, target.height); + xv->vp.full_width = target.width; + xv->vp.full_height = target.width; if (msg) xv_render_msg(xv, msg, width << 1, height << 1); diff --git a/retroarch.cfg b/retroarch.cfg index 65b77527e0..46d01d83be 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -71,6 +71,11 @@ # Forces rendering area to stay equal to game aspect ratio or as defined in video_aspect_ratio. # video_force_aspect = true +# Only scales video in integer steps. +# The base size depends on system-reported geometry and aspect ratio. +# If video_force_aspect is not set, X/Y will be integer scaled independently. +# video_scale_integer = false + # A floating point value for video aspect ratio (width / height). # If this is not set, aspect ratio is assumed to be automatic. # Behavior then is defined by video_aspect_ratio_auto. diff --git a/settings.c b/settings.c index 3eca9cb599..500b3f9f15 100644 --- a/settings.c +++ b/settings.c @@ -161,6 +161,7 @@ void config_set_defaults(void) g_settings.video.vsync = vsync; g_settings.video.smooth = video_smooth; g_settings.video.force_aspect = force_aspect; + g_settings.video.scale_integer = scale_integer; g_settings.video.crop_overscan = crop_overscan; g_settings.video.aspect_ratio = aspect_ratio; g_settings.video.aspect_ratio_auto = aspect_ratio_auto; // Let implementation decide if automatic, or 1:1 PAR. @@ -436,6 +437,7 @@ bool config_load_file(const char *path) CONFIG_GET_BOOL(video.vsync, "video_vsync"); CONFIG_GET_BOOL(video.smooth, "video_smooth"); CONFIG_GET_BOOL(video.force_aspect, "video_force_aspect"); + CONFIG_GET_BOOL(video.scale_integer, "video_scale_integer"); CONFIG_GET_BOOL(video.crop_overscan, "video_crop_overscan"); CONFIG_GET_FLOAT(video.aspect_ratio, "video_aspect_ratio"); CONFIG_GET_BOOL(video.aspect_ratio_auto, "video_aspect_ratio_auto");