diff options
| author | Dom Cobley <popcornmix@gmail.com> | 2022-11-02 16:12:00 +0000 |
|---|---|---|
| committer | Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> | 2022-11-04 19:12:43 +0200 |
| commit | adc05b66548d10ad8c4a400fb8e8b072a2fd8e2c (patch) | |
| tree | 617d30d43283071f9327049f539ffc13ac5da9f1 /kms++/src | |
| parent | 8cf1bdb791f008b0728a0de37e1f1b6648521ac2 (diff) | |
kmsprint: Decode bitfields for flags and type of hdmi mode
Decode the bitfields for the mode type and flags of Videomode
Use short names for type as it allows for consise formatting
(excluding the deprecated options, that are not expected to
be seen)
I've swapped order of flags and types as the type is expected
to be shorted so can fit in a fixed size field
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Diffstat (limited to 'kms++/src')
| -rw-r--r-- | kms++/src/videomode.cpp | 117 |
1 files changed, 111 insertions, 6 deletions
diff --git a/kms++/src/videomode.cpp b/kms++/src/videomode.cpp index b039059..0e5acf6 100644 --- a/kms++/src/videomode.cpp +++ b/kms++/src/videomode.cpp @@ -110,18 +110,123 @@ static char sync_to_char(SyncPolarity pol) } } +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +template<typename T> +std::string join(const T& values, const std::string& delim) +{ + std::ostringstream ss; + for (const auto& v : values) { + if (&v != &values[0]) + ss << delim; + ss << v; + } + return ss.str(); +} + +static const map<int, string> mode_type_map = { + // the deprecated ones don't care about a short name + { DRM_MODE_TYPE_BUILTIN, "builtin" }, // deprecated + { DRM_MODE_TYPE_CLOCK_C, "clock_c" }, // deprecated + { DRM_MODE_TYPE_CRTC_C, "crtc_c" }, // deprecated + { DRM_MODE_TYPE_PREFERRED, "P" }, + { DRM_MODE_TYPE_DEFAULT, "default" }, // deprecated + { DRM_MODE_TYPE_USERDEF, "U" }, + { DRM_MODE_TYPE_DRIVER, "D" }, +}; + +static const map<int, string> mode_flag_map = { + // the first 5 flags are displayed elsewhere + { DRM_MODE_FLAG_PHSYNC, "" }, + { DRM_MODE_FLAG_NHSYNC, "" }, + { DRM_MODE_FLAG_PVSYNC, "" }, + { DRM_MODE_FLAG_NVSYNC, "" }, + { DRM_MODE_FLAG_INTERLACE, "" }, + { DRM_MODE_FLAG_DBLSCAN, "dblscan" }, + { DRM_MODE_FLAG_CSYNC, "csync" }, + { DRM_MODE_FLAG_PCSYNC, "pcsync" }, + { DRM_MODE_FLAG_NCSYNC, "ncsync" }, + { DRM_MODE_FLAG_HSKEW, "hskew" }, + { DRM_MODE_FLAG_BCAST, "bcast" }, // deprecated + { DRM_MODE_FLAG_PIXMUX, "pixmux" }, // deprecated + { DRM_MODE_FLAG_DBLCLK, "2x" }, + { DRM_MODE_FLAG_CLKDIV2, "clkdiv2" }, +}; + +static const map<int, string> mode_3d_map = { + { DRM_MODE_FLAG_3D_NONE, "" }, + { DRM_MODE_FLAG_3D_FRAME_PACKING, "3dfp" }, + { DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE, "3dfa" }, + { DRM_MODE_FLAG_3D_LINE_ALTERNATIVE, "3dla" }, + { DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL, "3dsbs" }, + { DRM_MODE_FLAG_3D_L_DEPTH, "3dldepth" }, + { DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH, "3dgfx" }, + { DRM_MODE_FLAG_3D_TOP_AND_BOTTOM, "3dtab" }, + { DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF, "3dsbs" }, +}; + +static const map<int, string> mode_aspect_map = { + { DRM_MODE_FLAG_PIC_AR_NONE, "" }, + { DRM_MODE_FLAG_PIC_AR_4_3, "4:3" }, + { DRM_MODE_FLAG_PIC_AR_16_9, "16:9" }, + { DRM_MODE_FLAG_PIC_AR_64_27, "64:27" }, + { DRM_MODE_FLAG_PIC_AR_256_135, "256:135" }, +}; + +static string mode_type_str(uint32_t val) { + vector<string> s; + for (const auto & [k, v] : mode_type_map) { + if (val & k) { + if (!v.empty()) + s.push_back(v); + val &= ~k; + } + } + // any unknown bits + if (val != 0) + s.push_back(fmt::format("{:#x}", val)); + return join(s, "|"); +} + +static string mode_flag_str(uint32_t val) { + vector<string> s; + for (const auto& [k, v] : mode_flag_map) { + if (val & k) { + if (!v.empty()) + s.push_back(v); + val &= ~k; + } + } + auto it = mode_3d_map.find(val & DRM_MODE_FLAG_3D_MASK); + if (it != mode_3d_map.end()) { + if (!it->second.empty()) + s.push_back(it->second); + val &= ~DRM_MODE_FLAG_3D_MASK; + } + it = mode_aspect_map.find(val & DRM_MODE_FLAG_PIC_AR_MASK); + if (it != mode_aspect_map.end()) { + if (!it->second.empty()) + s.push_back(it->second); + val &= ~DRM_MODE_FLAG_PIC_AR_MASK; + } + // any unknown bits + if (val != 0) + s.push_back(fmt::format("{:#x}", val)); + return join(s, "|"); +} + string Videomode::to_string_long() const { string h = fmt::format("{}/{}/{}/{}/{}", hdisplay, hfp(), hsw(), hbp(), sync_to_char(hsync())); string v = fmt::format("{}/{}/{}/{}/{}", vdisplay, vfp(), vsw(), vbp(), sync_to_char(vsync())); - string str = fmt::format("{} {:.3f} {} {} {} ({:.2f}) {:#x} {:#x}", + string str = fmt::format("{} {:.3f} {} {} {} ({:.2f}) {} {}", to_string_short(), clock / 1000.0, h, v, vrefresh, calculated_vrefresh(), - flags, - type); + mode_type_str(type), + mode_flag_str(flags)); return str; } @@ -131,13 +236,13 @@ string Videomode::to_string_long_padded() const string h = fmt::format("{}/{}/{}/{}/{}", hdisplay, hfp(), hsw(), hbp(), sync_to_char(hsync())); string v = fmt::format("{}/{}/{}/{}/{}", vdisplay, vfp(), vsw(), vbp(), sync_to_char(vsync())); - string str = fmt::format("{:<16} {:7.3f} {:<18} {:<18} {:2} ({:.2f}) {:#10x} {:#6x}", + string str = fmt::format("{:<16} {:7.3f} {:<18} {:<18} {:2} ({:.2f}) {:<5} {}", to_string_short(), clock / 1000.0, h, v, vrefresh, calculated_vrefresh(), - flags, - type); + mode_type_str(type), + mode_flag_str(flags)); return str; } |
