Skip to content

Commit

Permalink
Fullscreen refresh rate improvements
Browse files Browse the repository at this point in the history
Handle refresh rate as float in general, and add also extra
attributes (interlaced, doublescan) for video modes.

Make it possible to select exact mode (interlaced / doublescan modes
will not be selected), and allow close matches such as 49.5 Hz
for PAL 50 Hz.
  • Loading branch information
zoltanvb authored and LibretroAdmin committed Jun 17, 2024
1 parent 622736e commit 2ca9737
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 10 deletions.
11 changes: 10 additions & 1 deletion gfx/display_servers/dispserv_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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++;
Expand Down
7 changes: 7 additions & 0 deletions gfx/display_servers/dispserv_win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand All @@ -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++)
Expand Down Expand Up @@ -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;

Expand Down
3 changes: 3 additions & 0 deletions gfx/video_display_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 8 additions & 3 deletions gfx/video_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
9 changes: 5 additions & 4 deletions menu/cbs/menu_cbs_ok.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* If not, see <http://www.gnu.org/licenses/>.
*/

#include <math.h>
#include <compat/strl.h>
#include <array/rbuf.h>
#include <file/file_path.h>
Expand Down Expand Up @@ -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");
Expand All @@ -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
Expand All @@ -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;
Expand Down
14 changes: 12 additions & 2 deletions menu/menu_displaylist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 2ca9737

Please sign in to comment.