DisplayServer (Windows): support precise refresh rate

This commit is contained in:
李通洲
2023-03-22 14:59:24 +08:00
parent b3da6b0e89
commit dcd0f8d3f6
8 changed files with 68 additions and 49 deletions
+1 -19
View File
@@ -1,25 +1,7 @@
#include "displayserver.h"
#include "detection/internal.h"
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
{
if(refreshRate <= 0)
return 0;
int remainder = refreshRate % 5;
if(remainder >= 3)
refreshRate += (5 - remainder);
else
refreshRate -= remainder;
//All other typicall refresh rates are dividable by 5
if(refreshRate == 145)
refreshRate = 144;
return (uint32_t) refreshRate;
}
bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight)
bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, double refreshRate, uint32_t scaledWidth, uint32_t scaledHeight)
{
if(width == 0 || height == 0)
return false;
+2 -5
View File
@@ -38,7 +38,7 @@ typedef struct FFDisplayResult
{
uint32_t width;
uint32_t height;
uint32_t refreshRate;
double refreshRate;
uint32_t scaledWidth;
uint32_t scaledHeight;
} FFDisplayResult;
@@ -55,9 +55,6 @@ typedef struct FFDisplayServerResult
} FFDisplayServerResult;
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance);
//Used internal
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight);
bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, double refreshRate, uint32_t scaledWidth, uint32_t scaledHeight);
#endif
@@ -39,7 +39,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
ffdsAppendDisplay(ds,
(uint32_t)CGDisplayModeGetPixelWidth(mode),
(uint32_t)CGDisplayModeGetPixelHeight(mode),
(uint32_t)refreshRate,
refreshRate,
(uint32_t)CGDisplayModeGetWidth(mode),
(uint32_t)CGDisplayModeGetHeight(mode)
);
@@ -1,5 +1,6 @@
#include "displayserver.h"
#include "detection/os/os.h"
#include "util/windows/unicode.h"
#include <dwmapi.h>
#include <WinUser.h>
@@ -11,6 +12,7 @@ typedef struct
uint32_t height;
} DataBundle;
static CALLBACK WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam)
{
MONITORINFOEXW mi = { .cbSize = sizeof(mi) };
@@ -45,22 +47,64 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
ffStrbufInit(&ds->deVersion);
ffListInit(&ds->displays, sizeof(FFDisplayResult));
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) };
for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum)
{
if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) };
if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0)
continue;
DISPLAYCONFIG_PATH_INFO paths[128];
uint32_t pathCount = sizeof(paths) / sizeof(paths[0]);
DISPLAYCONFIG_MODE_INFO modes[256];
uint32_t modeCount = sizeof(modes) / sizeof(modes[0]);
DataBundle data = {
.deviceName = displayDevice.DeviceName,
.width = 0,
.height = 0,
};
EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM)&data);
ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, data.width, data.height);
if (SUCCEEDED(QueryDisplayConfig(
QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE | 0x00000040 /*QDC_VIRTUAL_REFRESH_RATE_AWARE*/,
&pathCount,
paths,
&modeCount,
modes,
NULL)))
{
for (uint32_t i = 0; i < modeCount; ++i)
{
DISPLAYCONFIG_MODE_INFO* mode = &modes[i];
if(mode->infoType != DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
continue;
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {
.header = {
.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
.size = sizeof(sourceName),
.adapterId = mode->adapterId,
.id = mode->id,
},
};
DataBundle data = {};
if(SUCCEEDED(DisplayConfigGetDeviceInfo(&sourceName.header)))
{
data.deviceName = sourceName.viewGdiDeviceName;
EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM) &data);
}
// Find the target (monitor) friendly name
DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {
.header = {
.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
.size = sizeof(targetName),
.adapterId = mode->adapterId,
.id = mode->id,
},
};
FFstrbuf name;
ffStrbufInit(&name);
if(SUCCEEDED(DisplayConfigGetDeviceInfo(&targetName.header)) && targetName.flags.friendlyNameFromEdid)
ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName);
ffdsAppendDisplay(
ds,
mode->targetMode.targetVideoSignalInfo.totalSize.cx,
mode->targetMode.targetVideoSignalInfo.totalSize.cy,
mode->targetMode.targetVideoSignalInfo.vSyncFreq.Numerator / (double) mode->targetMode.targetVideoSignalInfo.vSyncFreq.Denominator,
data.width,
data.height);
}
}
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
+1 -1
View File
@@ -123,7 +123,7 @@ static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* regist
ffdsAppendDisplay(wldata->result,
(uint32_t) display.width,
(uint32_t) display.height,
ffdsParseRefreshRate(display.refreshRate / 1000),
display.refreshRate / 1000.0,
(uint32_t) (display.width / display.scale),
(uint32_t) (display.height / display.scale)
);
+1 -3
View File
@@ -174,9 +174,7 @@ typedef struct XcbRandrData
static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo)
{
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
modeInfo->dot_clock / (uint32_t) (modeInfo->htotal * modeInfo->vtotal)
));
double refreshRate = modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal);
return ffdsAppendDisplay(
data->result,
+1 -3
View File
@@ -133,9 +133,7 @@ typedef struct XrandrData
static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
{
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)
));
double refreshRate = modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal);
return ffdsAppendDisplay(
data->result,
+2 -2
View File
@@ -25,7 +25,7 @@ void ffPrintDisplay(FFinstance* instance)
printf("%ix%i", result->width, result->height);
if(result->refreshRate > 0)
printf(" @ %iHz", result->refreshRate);
printf(" @ %iHz", (uint32_t) (result->refreshRate + 0.5));
if(
result->scaledWidth > 0 && result->scaledWidth != result->width &&
@@ -39,7 +39,7 @@ void ffPrintDisplay(FFinstance* instance)
ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.display, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_UINT, &result->width},
{FF_FORMAT_ARG_TYPE_UINT, &result->height},
{FF_FORMAT_ARG_TYPE_UINT, &result->refreshRate},
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->refreshRate},
{FF_FORMAT_ARG_TYPE_UINT, &result->scaledWidth},
{FF_FORMAT_ARG_TYPE_UINT, &result->scaledHeight}
});