From 4f7d3b5ea03867c9de3a00b750fdcad9e21cc381 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 20 Apr 2013 12:48:33 +0200 Subject: [PATCH] Add custom viewport + integer scale mode. --- frontend/menu/rgui.c | 135 +++++++++++++++++++++++++++++++------------ gfx/gfx_common.c | 69 +++++++++++++--------- 2 files changed, 138 insertions(+), 66 deletions(-) diff --git a/frontend/menu/rgui.c b/frontend/menu/rgui.c index 2bd27db0d8..e1bb63a51f 100644 --- a/frontend/menu/rgui.c +++ b/frontend/menu/rgui.c @@ -220,7 +220,11 @@ rgui_handle_t *rgui_init(void) // before it's configured. rarch_viewport_t *custom = &g_extern.console.screen.viewports.custom_vp; if (driver.video_data && (!custom->width || !custom->height)) + { driver.video->viewport_info(driver.video_data, custom); + aspectratio_lut[ASPECT_RATIO_CUSTOM].value = + (float)custom->width / custom->height; + } return rgui; } @@ -1376,16 +1380,23 @@ static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) unsigned menu_type = 0; rgui_list_get_last(rgui->menu_stack, NULL, &menu_type); + struct retro_game_geometry *geom = &g_extern.system.av_info.geometry; + int stride_x = g_settings.video.scale_integer ? + geom->base_width : 1; + int stride_y = g_settings.video.scale_integer ? + geom->base_height : 1; + switch (action) { case RGUI_ACTION_UP: if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) { - custom->y -= 1; - custom->height += 1; + custom->y -= stride_y; + custom->height += stride_y; } - else - custom->height -= 1; + else if (custom->height >= (unsigned)stride_y) + custom->height -= stride_y; + if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); break; @@ -1393,11 +1404,13 @@ static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) case RGUI_ACTION_DOWN: if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) { - custom->y += 1; - custom->height -= 1; + custom->y += stride_y; + if (custom->height >= stride_y) + custom->height -= stride_y; } else - custom->height += 1; + custom->height += stride_y; + if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); break; @@ -1405,11 +1418,12 @@ static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) case RGUI_ACTION_LEFT: if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) { - custom->x -= 1; - custom->width += 1; + custom->x -= stride_x; + custom->width += stride_x; } - else - custom->width -= 1; + else if (custom->width >= (unsigned)stride_x) + custom->width -= stride_x; + if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); break; @@ -1417,11 +1431,13 @@ static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) case RGUI_ACTION_RIGHT: if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) { - custom->x += 1; - custom->width -= 1; + custom->x += stride_x; + if (custom->width >= (unsigned)stride_x) + custom->width -= stride_x; } else - custom->width += 1; + custom->width += stride_x; + if (driver.video_poke->apply_state_changes) driver.video_poke->apply_state_changes(driver.video_data); break; @@ -1429,34 +1445,46 @@ static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) case RGUI_ACTION_CANCEL: rgui_list_pop(rgui->menu_stack, &rgui->selection_ptr); if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2) - rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_VIEWPORT, + { + rgui_list_push(rgui->menu_stack, "", + RGUI_SETTINGS_CUSTOM_VIEWPORT, rgui->selection_ptr); + } break; case RGUI_ACTION_OK: rgui_list_pop(rgui->menu_stack, &rgui->selection_ptr); - if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) - rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_VIEWPORT_2, + if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT + && !g_settings.video.scale_integer) + { + rgui_list_push(rgui->menu_stack, "", + RGUI_SETTINGS_CUSTOM_VIEWPORT_2, rgui->selection_ptr); + } break; case RGUI_ACTION_START: -#ifdef GEKKO - if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) + if (!g_settings.video.scale_integer) { - custom->width += custom->x; - custom->height += custom->y; - custom->x = 0; - custom->y = 0; + rarch_viewport_t vp; + driver.video->viewport_info(driver.video_data, &vp); + + if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) + { + custom->width += custom->x; + custom->height += custom->y; + custom->x = 0; + custom->y = 0; + } + else + { + custom->width = vp.full_width - custom->x; + custom->height = vp.full_height - custom->y; + } + + if (driver.video_poke->apply_state_changes) + driver.video_poke->apply_state_changes(driver.video_data); } - else - { - custom->width = win_width - custom->x; - custom->height = win_height - custom->y; - } -#endif - if (driver.video_poke->apply_state_changes) - driver.video_poke->apply_state_changes(driver.video_data); break; case RGUI_ACTION_SETTINGS: @@ -1476,16 +1504,45 @@ static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) render_text(rgui); const char *base_msg = NULL; - if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) - base_msg = "Set Upper-Left Corner"; - else if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2) - base_msg = "Set Bottom-Right Corner"; - char msg[64]; - snprintf(msg, sizeof(msg), "%s (%d, %d : %4ux%4u)", - base_msg, custom->x, custom->y, custom->width, custom->height); + + if (g_settings.video.scale_integer) + { + custom->x = 0; + custom->y = 0; + custom->width = ((custom->width + geom->base_width - 1) / geom->base_width) * geom->base_width; + custom->height = ((custom->height + geom->base_height - 1) / geom->base_height) * geom->base_height; + + base_msg = "Set scale"; + snprintf(msg, sizeof(msg), "%s (%4ux%4u, %u x %u scale)", + base_msg, + custom->width, custom->height, + custom->width / geom->base_width, + custom->height / geom->base_height); + } + else + { + if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT) + base_msg = "Set Upper-Left Corner"; + else if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2) + base_msg = "Set Bottom-Right Corner"; + + snprintf(msg, sizeof(msg), "%s (%d, %d : %4ux%4u)", + base_msg, custom->x, custom->y, custom->width, custom->height); + } render_messagebox(rgui, msg); + if (!custom->width) + custom->width = stride_x; + if (!custom->height) + custom->height = stride_y; + + aspectratio_lut[ASPECT_RATIO_CUSTOM].value = + (float)custom->width / custom->height; + + if (driver.video_poke->apply_state_changes) + driver.video_poke->apply_state_changes(driver.video_data); + return 0; } @@ -1569,6 +1626,8 @@ static int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action) // Start with something sane. rarch_viewport_t *custom = &g_extern.console.screen.viewports.custom_vp; driver.video->viewport_info(driver.video_data, custom); + aspectratio_lut[ASPECT_RATIO_CUSTOM].value = + (float)custom->width / custom->height; g_settings.video.aspect_ratio_idx = ASPECT_RATIO_CUSTOM; if (driver.video_poke->set_aspect_ratio) diff --git a/gfx/gfx_common.c b/gfx/gfx_common.c index cde4cb2af0..4b0906494e 100644 --- a/gfx/gfx_common.c +++ b/gfx/gfx_common.c @@ -128,40 +128,53 @@ void gfx_set_dwm(void) 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); + int padding_x = 0; + int padding_y = 0; - 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 (g_settings.video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM) { - 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; - } - } + const struct rarch_viewport *custom = + &g_extern.console.screen.viewports.custom_vp; - width -= padding_x; - height -= padding_y; + padding_x = width - custom->width; + padding_y = height - custom->height; + width = custom->width; + height = custom->height; + } + else + { + // 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); + + // 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; + vp->x = padding_x / 2; + vp->y = padding_y / 2; } struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END] = {