Add integer scale options.

This commit is contained in:
Themaister 2013-01-29 19:28:33 +01:00
parent ab2ed14738
commit 61707d2783
8 changed files with 80 additions and 9 deletions

View File

@ -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

View File

@ -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];

View File

@ -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;
}

View File

@ -21,6 +21,7 @@ extern "C" {
#endif
#include <stddef.h>
#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

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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");