summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDom Cobley <popcornmix@gmail.com>2022-11-02 16:12:00 +0000
committerTomi Valkeinen <tomi.valkeinen@ideasonboard.com>2022-11-04 19:12:43 +0200
commitadc05b66548d10ad8c4a400fb8e8b072a2fd8e2c (patch)
tree617d30d43283071f9327049f539ffc13ac5da9f1
parent8cf1bdb791f008b0728a0de37e1f1b6648521ac2 (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>
-rw-r--r--kms++/src/videomode.cpp117
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;
}