Fullscreen refresh rate improvements

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.
This commit is contained in:
zoltanvb 2024-06-16 11:56:04 +02:00 committed by LibretroAdmin
parent 622736e195
commit 2ca973770f
6 changed files with 45 additions and 10 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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