diff --git a/gfx/display_servers/dispserv_kms.c b/gfx/display_servers/dispserv_kms.c index c42f5c0ac3b..086b4631cd9 100644 --- a/gfx/display_servers/dispserv_kms.c +++ b/gfx/display_servers/dispserv_kms.c @@ -123,6 +123,8 @@ static void *kms_display_server_get_resolution_list( unsigned curr_width = 0; unsigned curr_height = 0; unsigned curr_bpp = 0; + bool curr_interlaced = false; + bool curr_dblscan = false; float curr_refreshrate = 0; unsigned curr_orientation = 0; struct video_display_config *conf = NULL; @@ -134,6 +136,8 @@ static void *kms_display_server_get_resolution_list( curr_width = g_drm_mode->hdisplay; curr_height = g_drm_mode->vdisplay; curr_bpp = 32; + curr_interlaced = (g_drm_mode->flags & DRM_MODE_FLAG_INTERLACE) ? true : false; + curr_dblscan = (g_drm_mode->flags & DRM_MODE_FLAG_DBLSCAN) ? true : false; } *len = g_drm_connector->count_modes; @@ -147,13 +151,18 @@ static void *kms_display_server_get_resolution_list( conf[j].height = g_drm_connector->modes[i].vdisplay; conf[j].bpp = 32; conf[j].refreshrate = floor(drm_calc_refresh_rate(&g_drm_connector->modes[i])); + conf[j].refreshrate_float = drm_calc_refresh_rate(&g_drm_connector->modes[i]); + conf[j].interlaced = (g_drm_connector->modes[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false; + conf[j].dblscan = (g_drm_connector->modes[i].flags & DRM_MODE_FLAG_DBLSCAN) ? true : false; conf[j].idx = j; conf[j].current = false; if ( (conf[j].width == curr_width) && (conf[j].height == curr_height) && (conf[j].bpp == curr_bpp) - && (drm_calc_refresh_rate(&g_drm_connector->modes[i]) == curr_refreshrate) + && (conf[j].refreshrate_float == curr_refreshrate) + && (conf[j].interlaced == curr_interlaced) + && (conf[j].dblscan == curr_dblscan) ) conf[j].current = true; j++; diff --git a/gfx/display_servers/dispserv_win32.c b/gfx/display_servers/dispserv_win32.c index 0d288d30591..81c8883d61c 100644 --- a/gfx/display_servers/dispserv_win32.c +++ b/gfx/display_servers/dispserv_win32.c @@ -356,6 +356,7 @@ static void *win32_display_server_get_resolution_list( #if _WIN32_WINNT >= 0x0500 unsigned curr_orientation = 0; #endif + bool curr_interlaced = false; struct video_display_config *conf = NULL; if (win32_get_video_output(&dm, -1, sizeof(dm))) @@ -367,6 +368,7 @@ static void *win32_display_server_get_resolution_list( #if _WIN32_WINNT >= 0x0500 curr_orientation = dm.dmDisplayOrientation; #endif + curr_interlaced = (dm.dmDisplayFlags & DM_INTERLACED) ? true : false; } for (i = 0; win32_get_video_output(&dm, i, sizeof(dm)); i++) @@ -403,13 +405,18 @@ static void *win32_display_server_get_resolution_list( conf[j].height = dm.dmPelsHeight; conf[j].bpp = dm.dmBitsPerPel; conf[j].refreshrate = dm.dmDisplayFrequency; + /* It may be possible to get exact refresh rate via different API - for now, it is integer only */ + conf[j].refreshrate_float = 0.0f; conf[j].idx = j; conf[j].current = false; + conf[j].interlaced = (dm.dmDisplayFlags & DM_INTERLACED) ? true : false; + conf[j].dblscan = false; /* no flag for doublescan on this platform */ if ( (conf[j].width == curr_width) && (conf[j].height == curr_height) && (conf[j].bpp == curr_bpp) && (conf[j].refreshrate == curr_refreshrate) + && (conf[j].interlaced == curr_interlaced) ) conf[j].current = true; diff --git a/gfx/video_display_server.h b/gfx/video_display_server.h index f29ac527e3d..be6a7088cc6 100644 --- a/gfx/video_display_server.h +++ b/gfx/video_display_server.h @@ -39,6 +39,9 @@ typedef struct video_display_config unsigned refreshrate; unsigned idx; bool current; + bool interlaced; + bool dblscan; + float refreshrate_float; } video_display_config_t; typedef struct video_display_server diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 509edc6bc29..21638a07831 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -1214,9 +1214,14 @@ bool video_display_server_has_refresh_rate(float hz) for (i = 0; i < size && !rate_exists; i++) { - if ( (video_list[i].width == video_driver_width) - && (video_list[i].height == video_driver_height) - && (video_list[i].refreshrate == floor(hz))) + /* Float difference added to enable 49.95Hz modelines for PAL. * + * Actual mode selection will be done in context driver, * + * with some logic in video_switch_refresh_rate_maybe * + * and in action_cb_push_dropdown_item_resolution */ + if ( (video_list[i].width == video_driver_width) + && (video_list[i].height == video_driver_height) + && ((video_list[i].refreshrate == floor(hz)) || + (fabsf(video_list[i].refreshrate_float - hz) < 0.06f))) rate_exists = true; } diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index ea4e5b58cd4..323817dc4d3 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -15,6 +15,7 @@ * If not, see . */ +#include #include #include #include @@ -6928,7 +6929,7 @@ int action_cb_push_dropdown_item_resolution(const char *path, char *pch = NULL; unsigned width = 0; unsigned height = 0; - unsigned refreshrate = 0; + float refreshrate = 0.0f; strlcpy(str, path, sizeof(str)); pch = strtok(str, "x"); @@ -6939,10 +6940,10 @@ int action_cb_push_dropdown_item_resolution(const char *path, height = (unsigned)strtoul(pch, NULL, 0); pch = strtok(NULL, "("); if (pch) - refreshrate = (unsigned)strtoul(pch, NULL, 0); + refreshrate = (float)strtod(pch, NULL); if (video_display_server_set_resolution(width, height, - refreshrate, (float)refreshrate, 0, 0, 0, 0)) + floor(refreshrate), refreshrate, 0, 0, 0, 0)) { settings_t *settings = config_get_ptr(); #ifdef _MSC_VER @@ -6954,7 +6955,7 @@ int action_cb_push_dropdown_item_resolution(const char *path, float refresh_exact = refreshrate; /* 59 Hz is an inaccurate representation of the real value (59.94). - * And since we at this point only have the integer to work with, + * In case at this point we only have the integer to work with, * the exact float needs to be calculated for 'video_refresh_rate' */ if (refreshrate == (60.0f * refresh_mod) - 1) refresh_exact = 59.94f * refresh_mod; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index a37ea784c63..a3ad3bd449c 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -8350,10 +8350,20 @@ unsigned menu_displaylist_build_list( for (i = 0; i < size; i++) { char val_d[256], str[256]; - snprintf(str, sizeof(str), "%dx%d (%d Hz)", + /* If there is exact refresh rate available, use it */ + if (video_list[i].refreshrate_float > 0.0f) + snprintf(str, sizeof(str), "%dx%d (%.3f Hz)%s%s", video_list[i].width, video_list[i].height, - video_list[i].refreshrate); + video_list[i].refreshrate_float, + video_list[i].interlaced ? "[i]":"", + video_list[i].dblscan ? "[d]":""); + else + snprintf(str, sizeof(str), "%dx%d (%d Hz)%s", + video_list[i].width, + video_list[i].height, + video_list[i].refreshrate, + video_list[i].interlaced ? "[i]":""); snprintf(val_d, sizeof(val_d), "%d", i); if (menu_entries_append(list, str,