From 64ec76f5a67ddc836d3d49d7800d27ce7eb20d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Apr 2024 09:52:55 +0800 Subject: [PATCH] Display (Linux): detect refresh rate for DRM method --- src/detection/displayserver/linux/drm.c | 61 ++++++++++++------------- src/util/edidHelper.c | 19 ++++++++ src/util/edidHelper.h | 1 + 3 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index f76df154b..3710f1db2 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -36,31 +36,28 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) continue; } - ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); - ffStrbufAppendS(&drmDir, "/modes"); - - char modes[32]; - if (ffReadFileData(drmDir.chars, sizeof(modes), modes) < 3) - { - ffStrbufSubstrBefore(&drmDir, drmDirLength); - continue; - } - unsigned width = 0, height = 0; + double refreshRate = 0; + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); - int scanned = sscanf(modes, "%ux%u", &width, &height); - if(scanned == 2 && width > 0 && height > 0) + ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); + ffStrbufAppendS(&drmDir, "/edid"); + + uint8_t edidData[128]; + if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) { - ffStrbufSubstrBefore(&drmDir, drmDirLength); - ffStrbufAppendS(&drmDir, entry->d_name); - ffStrbufAppendS(&drmDir, "/edid"); + ffEdidGetName(edidData, &name); + ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate); + } + else + { + ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); + ffStrbufAppendS(&drmDir, "/modes"); - FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); - uint8_t edidData[128]; - if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) - ffEdidGetName(edidData, &name); - else + char modes[32]; + if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3) { + sscanf(modes, "%ux%u", &width, &height); const char* plainName = entry->d_name; if (ffStrStartsWith(plainName, "card")) { @@ -69,20 +66,20 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) } ffStrbufAppendS(&name, plainName); } - - ffdsAppendDisplay( - result, - width, height, - 0, - 0, 0, - 0, - &name, - FF_DISPLAY_TYPE_UNKNOWN, - false, - 0 - ); } + ffdsAppendDisplay( + result, + width, height, + refreshRate, + 0, 0, + 0, + &name, + FF_DISPLAY_TYPE_UNKNOWN, + false, + 0 + ); + ffStrbufSubstrBefore(&drmDir, drmDirLength); } diff --git a/src/util/edidHelper.c b/src/util/edidHelper.c index 5fa2c662b..09931d22d 100644 --- a/src/util/edidHelper.c +++ b/src/util/edidHelper.c @@ -7,6 +7,25 @@ void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint3 *height = (((uint32_t) edid[dtd + 7] >> 4) << 8) | edid[dtd + 5]; } +void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate) +{ + for (uint32_t i = 0x36; i < 0x7E; i += 0x12) + { // read through descriptor blocks... + if (edid[i] != 0x00 && edid[i + 1] != 0x00) + { // a dtd + uint32_t hactive = edid[i+2] + ((edid[i + 4] & 0xf0) << 4); + uint32_t hblank = edid[i+3] + ((edid[i + 4] & 0x0f) << 8); + uint32_t vactive = edid[i+5] + ((edid[i + 7] & 0xf0) << 4); + uint32_t vblank = edid[i+6] + ((edid[i + 7] & 0x0f) << 8); + uint32_t pixclk = (edid[i+1] << 8) | (edid[i]); + *width = hactive; + *height = vactive; + *refreshRate = (double)pixclk * 10000 / (double)(hactive+hblank) / (double)(vactive+vblank); + return; + } + } +} + void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result) { // https://github.com/jinksong/read_edid/blob/master/parse-edid/parse-edid.c diff --git a/src/util/edidHelper.h b/src/util/edidHelper.h index 6e768ddf9..cad9e6ce9 100644 --- a/src/util/edidHelper.h +++ b/src/util/edidHelper.h @@ -5,6 +5,7 @@ void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result); bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name); +void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate); void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint32_t* height); void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* height); // in mm void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week);