summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/kmsprint.cpp562
1 files changed, 438 insertions, 124 deletions
diff --git a/utils/kmsprint.cpp b/utils/kmsprint.cpp
index a57d33f..cecba5c 100644
--- a/utils/kmsprint.cpp
+++ b/utils/kmsprint.cpp
@@ -1,142 +1,481 @@
#include <cstdio>
#include <algorithm>
#include <iostream>
+#include <string>
+#include <unistd.h>
+#include <inttypes.h>
#include "kms++.h"
#include "opts.h"
+#include "kms++util.h"
+#include "strhelpers.h"
using namespace std;
using namespace kms;
-namespace kmsprint {
-
static struct {
bool print_props;
bool print_modes;
- bool recurse;
-} opts;
+ bool print_list;
+ bool x_modeline;
+} s_opts;
-string width(int w, string str)
+static string format_mode(const Videomode& m, unsigned idx)
{
- str.resize(w, ' ');
+ string str;
+
+ str = sformat(" %2u ", idx);
+
+ if (s_opts.x_modeline) {
+ str += sformat("%12s %6d %4u %4u %4u %4u %4u %4u %4u %4u %2u %#x %#x",
+ m.name.c_str(),
+ m.clock,
+ m.hdisplay, m.hsync_start, m.hsync_end, m.htotal,
+ m.vdisplay, m.vsync_start, m.vsync_end, m.vtotal,
+ m.vrefresh,
+ m.flags,
+ m.type);
+ } else {
+ string h = sformat("%u/%u/%u/%u", m.hdisplay, m.hfp(), m.hsw(), m.hbp());
+ string v = sformat("%u/%u/%u/%u", m.vdisplay, m.vfp(), m.vsw(), m.vbp());
+
+ str += sformat("%-12s %6d %-16s %-16s %2u %#10x %#6x",
+ m.name.c_str(),
+ m.clock,
+ h.c_str(), v.c_str(),
+ m.vrefresh,
+ m.flags,
+ m.type);
+ }
+
return str;
}
-void print_mode(const Videomode &m, int ind)
+static string format_mode_short(const Videomode& m)
{
- printf("%s%s %6d %4d %4d %4d %4d %d %4d %4d %4d %4d %d %2d 0x%04x %2d\n",
- width(ind, "").c_str(),
- m.name[0] == '\0' ? "" : width(11, m.name).c_str(),
- m.clock,
- m.hdisplay,
- m.hsync_start,
- m.hsync_end,
- m.htotal,
- m.hskew,
- m.vdisplay,
- m.vsync_start,
- m.vsync_end,
- m.vtotal,
- m.vscan,
- m.vrefresh,
- m.flags,
- m.type);
+ string h = sformat("%u/%u/%u/%u", m.hdisplay, m.hfp(), m.hsw(), m.hbp());
+ string v = sformat("%u/%u/%u/%u", m.vdisplay, m.vfp(), m.vsw(), m.vbp());
+
+ return sformat("%s %d %s %s %u",
+ m.name.c_str(),
+ m.clock,
+ h.c_str(), v.c_str(),
+ m.vrefresh);
}
-void print_property(uint64_t val, const Property& p, int ind)
+static string format_connector(Connector& c)
{
- printf("%s%s (id %d) = %s\n", width(ind, "").c_str(),
- p.name().c_str(), p.id(), p.to_str(val).c_str());
+ string str;
+
+ str = sformat("Connector %u (%u) %s",
+ c.idx(), c.id(), c.fullname().c_str());
+
+ if (c.connected())
+ str += " (connected)";
+
+ return str;
}
-void print_properties(DrmPropObject& o, int ind)
+static string format_encoder(Encoder& e)
{
- auto pmap = o.get_prop_map();
- printf("%sProperties, %u in total:\n", width(ind, "").c_str(),
- (unsigned) pmap.size());
+ return sformat("Encoder %u (%u) %s",
+ e.idx(), e.id(), e.get_encoder_type().c_str());
+}
+
+static string format_crtc(Crtc& c)
+{
+ string str;
+
+ str = sformat("Crtc %u (%u)", c.idx(), c.id());
+
+ if (c.mode_valid())
+ str += " " + format_mode_short(c.mode());
+
+ return str;
+}
+
+static string format_plane(Plane& p)
+{
+ string str;
+
+ str = sformat("Plane %u (%u)", p.idx(), p.id());
+
+ if (p.fb_id())
+ str += sformat(" fb-id: %u", p.fb_id());
+
+ if (p.card().has_atomic()) {
+ str += sformat(" %u,%u %ux%u -> %u,%u %ux%u",
+ (uint32_t)p.get_prop_value("SRC_X") >> 16,
+ (uint32_t)p.get_prop_value("SRC_Y") >> 16,
+ (uint32_t)p.get_prop_value("SRC_W") >> 16,
+ (uint32_t)p.get_prop_value("SRC_H") >> 16,
+ (uint32_t)p.get_prop_value("CRTC_X"),
+ (uint32_t)p.get_prop_value("CRTC_Y"),
+ (uint32_t)p.get_prop_value("CRTC_W"),
+ (uint32_t)p.get_prop_value("CRTC_H"));
+ }
+
+ return str;
+}
+
+static string format_fb(Framebuffer& fb)
+{
+ return sformat("FB %u %ux%u",
+ fb.id(), fb.width(), fb.height());
+}
+
+static string format_property(const Property* prop, uint64_t val)
+{
+ string ret = sformat("%s = ", prop->name().c_str());
+
+ switch (prop->type()) {
+ case PropertyType::Bitmask:
+ {
+ vector<string> v, vall;
+
+ for (auto kvp : prop->get_enums()) {
+ if (val & (1 << kvp.first))
+ v.push_back(kvp.second);
+ vall.push_back(kvp.second);
+ }
+
+ ret += sformat("%s (%s)", join(v, "|").c_str(), join(vall, "|").c_str());
+
+ break;
+ }
+
+ case PropertyType::Blob:
+ {
+ uint32_t blob_id = (uint32_t)val;
+
+ if (blob_id) {
+ Blob blob(prop->card(), blob_id);
+ auto data = blob.data();
+
+ ret += sformat("blob-id %u len %zu", blob_id, data.size());
+ } else {
+ ret += sformat("blob-id %u", blob_id);
+ }
+
+ break;
+ }
+
+ case PropertyType::Enum:
+ {
+ string cur;
+ vector<string> vall;
+
+ for (auto kvp : prop->get_enums()) {
+ if (val == kvp.first)
+ cur = kvp.second;
+ vall.push_back(kvp.second);
+ }
+
+ ret += sformat("%s (%s)", cur.c_str(), join(vall, "|").c_str());
+
+ break;
+ }
+
+ case PropertyType::Object:
+ {
+ ret += sformat("object id %u", (uint32_t)val);
+ break;
+ }
+
+ case PropertyType::Range:
+ {
+ auto values = prop->get_values();
+
+ ret += sformat("%" PRIu64 " [%" PRIu64 " - %" PRIu64 "]",
+ val, values[0], values[1]);
+
+ break;
+ }
+
+ case PropertyType::SignedRange:
+ {
+ auto values = prop->get_values();
+
+ ret += sformat("%" PRIi64 " [%" PRIi64 " - %" PRIi64 "]",
+ (int64_t)val, (int64_t)values[0], (int64_t)values[1]);
+
+ break;
+ }
+
+ }
+
+ if (prop->is_pending())
+ ret += " (pending)";
+ if (prop->is_immutable())
+ ret += " (immutable)";
+
+ return ret;
+}
+
+static vector<string> format_props(DrmPropObject* o)
+{
+ vector<string> lines;
+
+ auto pmap = o->get_prop_map();
for (auto pp : pmap) {
- const Property& p = *o.card().get_prop(pp.first);
- print_property(pp.second, p, ind + 2);
+ const Property* p = o->card().get_prop(pp.first);
+ lines.push_back(format_property(p, pp.second));
}
+
+ return lines;
+}
+
+static string format_ob(DrmObject* ob)
+{
+ if (auto o = dynamic_cast<Connector*>(ob))
+ return format_connector(*o);
+ else if (auto o = dynamic_cast<Encoder*>(ob))
+ return format_encoder(*o);
+ else if (auto o = dynamic_cast<Crtc*>(ob))
+ return format_crtc(*o);
+ else if (auto o = dynamic_cast<Plane*>(ob))
+ return format_plane(*o);
+ else if (auto o = dynamic_cast<Framebuffer*>(ob))
+ return format_fb(*o);
+ else
+ EXIT("Unkown DRM Object type\n");
}
-void print_plane(Plane& p, int ind)
+template<class T>
+vector<T> filter(const vector<T>& sequence, function<bool(T)> predicate)
{
- printf("%sPlane Id %d %d,%d -> %dx%d formats:", width(ind, "").c_str(),
- p.id(), p.crtc_x(), p.crtc_y(), p.x(), p.y());
- for (auto f : p.get_formats())
- printf(" %s", PixelFormatToFourCC(f).c_str());
- printf("\n");
+ vector<T> result;
+
+ for(auto it = sequence.begin(); it != sequence.end(); ++it)
+ if(predicate(*it))
+ result.push_back(*it);
- if (opts.print_props)
- print_properties(p, ind+2);
+ return result;
}
-void print_crtc(Crtc& cc, int ind)
+struct Entry
{
- printf("%sCRTC Id %d BufferId %d %dx%d at %dx%d gamma_size %d\n",
- width(ind, "").c_str(), cc.id(), cc.buffer_id(), cc.width(),
- cc.height(), cc.x(), cc.y(), cc.gamma_size());
+ string title;
+ vector<string> lines;
+ vector<Entry> children;
+};
- printf("%s Mode ", width(ind, "").c_str());
- print_mode(cc.mode(), 0);
+static Entry& add_entry(vector<Entry>& entries)
+{
+ entries.emplace_back();
+ return entries.back();
+}
+/*
+static bool on_tty()
+{
+ return isatty(STDOUT_FILENO) > 0;
+}
+*/
+enum class TreeGlyphMode {
+ None,
+ ASCII,
+ UTF8,
+};
+
+static TreeGlyphMode s_glyph_mode = TreeGlyphMode::None;
+
+enum class TreeGlyph {
+ Vertical,
+ Branch,
+ Right,
+ Space,
+};
+
+static const map<TreeGlyph, string> glyphs_utf8 = {
+ { TreeGlyph::Vertical, "│ " },
+ { TreeGlyph::Branch, "├─" },
+ { TreeGlyph::Right, "└─" },
+ { TreeGlyph::Space, " " },
+
+};
+
+static const map<TreeGlyph, string> glyphs_ascii = {
+ { TreeGlyph::Vertical, "| " },
+ { TreeGlyph::Branch, "|-" },
+ { TreeGlyph::Right, "`-" },
+ { TreeGlyph::Space, " " },
+
+};
+
+const char* get_glyph(TreeGlyph glyph)
+{
+ if (s_glyph_mode == TreeGlyphMode::None)
+ return " ";
- if (opts.print_props)
- print_properties(cc, ind+2);
+ const map<TreeGlyph, string>& glyphs = s_glyph_mode == TreeGlyphMode::UTF8 ? glyphs_utf8 : glyphs_ascii;
- if (opts.recurse)
- for (auto p : cc.get_possible_planes())
- print_plane(*p, ind + 2);
+ return glyphs.at(glyph).c_str();
}
-void print_encoder(Encoder& e, int ind)
+static void print_entry(const Entry& e, const string& prefix, bool is_child, bool is_last)
{
- printf("%sEncoder Id %d type %s\n", width(ind, "").c_str(),
- e.id(), e.get_encoder_type().c_str());
+ string prefix1;
+ string prefix2;
- if (opts.print_props)
- print_properties(e, ind+2);
+ if (is_child) {
+ prefix1 = prefix + (is_last ? get_glyph(TreeGlyph::Right) : get_glyph(TreeGlyph::Branch));
+ prefix2 = prefix + (is_last ? get_glyph(TreeGlyph::Space) : get_glyph(TreeGlyph::Vertical));
+ }
- if (opts.recurse)
- for (auto cc : e.get_possible_crtcs())
- print_crtc(*cc, ind + 2);
+ printf("%s%s\n", prefix1.c_str(), e.title.c_str());
+
+ bool has_children = e.children.size() > 0;
+
+ string data_prefix = prefix2 + (has_children ? get_glyph(TreeGlyph::Vertical) : get_glyph(TreeGlyph::Space));
+
+ for (const string& str : e.lines) {
+ string p = data_prefix + get_glyph(TreeGlyph::Space);
+ printf("%s%s\n", p.c_str(), str.c_str());
+ }
+
+ for (const Entry& child : e.children) {
+ bool is_last = &child == &e.children.back();
+
+ print_entry(child, prefix2, true, is_last);
+ }
}
-void print_connector(Connector& c, int ind)
+static void print_entries(const vector<Entry>& entries, const string& prefix)
{
- printf("%sConnector %s Id %d %sconnected", width(ind, "").c_str(),
- c.fullname().c_str(), c.id(), c.connected() ? "" : "dis");
- if (c.subpixel() != 0)
- printf(" Subpixel: %s", c.subpixel_str().c_str());
- printf("\n");
+ for (const Entry& e: entries) {
+ print_entry(e, "", false, false);
+ }
+}
+
+template<class T>
+static void append(vector<DrmObject*>& dst, const vector<T*>& src)
+{
+ dst.insert(dst.end(), src.begin(), src.end());
+}
+
+
+static void print_as_list(Card& card)
+{
+ vector<DrmPropObject*> obs;
+ vector<Framebuffer*> fbs;
+
+ for (Connector* conn : card.get_connectors()) {
+ obs.push_back(conn);
+ }
- if (opts.print_props)
- print_properties(c, ind+2);
+ for (Encoder* enc : card.get_encoders()) {
+ obs.push_back(enc);
+ }
- if (opts.recurse)
- for (auto enc : c.get_encoders())
- print_encoder(*enc, ind + 2);
+ for (Crtc* crtc : card.get_crtcs()) {
+ obs.push_back(crtc);
+ if (crtc->buffer_id() && !card.has_has_universal_planes()) {
+ Framebuffer* fb = new Framebuffer(card, crtc->buffer_id());
+ fbs.push_back(fb);
+ }
+ }
- if (opts.print_modes) {
- auto modes = c.get_modes();
- printf("%sModes, %u in total:\n", width(ind + 2, "").c_str(),
- (unsigned) modes.size());
- for (auto mode : modes)
- print_mode(mode, ind + 3);
+ for (Plane* plane : card.get_planes()) {
+ obs.push_back(plane);
+ if (plane->fb_id()) {
+ Framebuffer* fb = new Framebuffer(card, plane->fb_id());
+ fbs.push_back(fb);
+ }
+ }
+
+ for (DrmPropObject* ob: obs) {
+ printf("%s\n", format_ob(ob).c_str());
+
+ if (s_opts.print_props) {
+ for (string str : format_props(ob))
+ printf(" %s\n", str.c_str());
+ }
+ }
+
+ for (Framebuffer* fb: fbs) {
+ printf("%s\n", format_ob(fb).c_str());
}
}
+static void print_as_tree(Card& card)
+{
+ vector<Entry> entries;
+
+ for (Connector* conn : card.get_connectors()) {
+ if (!conn->connected())
+ continue;
+
+ Entry& e1 = add_entry(entries);
+ e1.title = format_ob(conn);
+ if (s_opts.print_props)
+ e1.lines = format_props(conn);
+
+ for (Encoder* enc : conn->get_encoders()) {
+
+ Entry& e2 = add_entry(e1.children);
+ e2.title = format_ob(enc);
+ if (s_opts.print_props)
+ e2.lines = format_props(enc);
+
+ if (Crtc* crtc = enc->get_crtc()) {
+ Entry& e3 = add_entry(e2.children);
+ e3.title = format_ob(crtc);
+ if (s_opts.print_props)
+ e3.lines = format_props(crtc);
+
+ if (crtc->buffer_id() && !card.has_has_universal_planes()) {
+ Framebuffer fb(card, crtc->buffer_id());
+ Entry& e5 = add_entry(e3.children);
+
+ e5.title = format_ob(&fb);
+ }
+
+ for (Plane* plane : card.get_planes()) {
+ if (plane->crtc_id() != crtc->id())
+ continue;
+
+ Entry& e4 = add_entry(e3.children);
+ e4.title = format_ob(plane);
+ if (s_opts.print_props)
+ e4.lines = format_props(plane);
+
+ uint32_t fb_id = plane->fb_id();
+ if (fb_id) {
+ Framebuffer fb(card, fb_id);
+
+ Entry& e5 = add_entry(e4.children);
+
+ e5.title = format_ob(&fb);
+ }
+ }
+ }
+ }
+ }
+
+ print_entries(entries, "");
}
-using namespace kmsprint;
+static void print_modes(Card& card)
+{
+ for (Connector* conn : card.get_connectors()) {
+ if (!conn->connected())
+ continue;
+
+ printf("%s\n", format_ob(conn).c_str());
+
+ auto modes = conn->get_modes();
+ for (unsigned i = 0; i < modes.size(); ++i)
+ printf("%s\n", format_mode(modes[i], i).c_str());
+ }
+}
static const char* usage_str =
"Usage: kmsprint [OPTIONS]\n\n"
"Options:\n"
+ " -l, --list Print list instead of tree\n"
" -m, --modes Print modes\n"
+ " --xmode Print modes using X modeline\n"
" -p, --props Print properties\n"
- " -r, --recurse Recursively print all related objects\n"
- " --id=<ID> Print object <ID>\n"
;
static void usage()
@@ -146,33 +485,29 @@ static void usage()
int main(int argc, char **argv)
{
- string dev_path;
- unsigned id = 0;
+ string dev_path = "/dev/dri/card0";
OptionSet optionset = {
- Option("|device=",
- [&](string s)
+ Option("|device=", [&dev_path](string s)
{
dev_path = s;
}),
- Option("|id=",
- [&](string s)
+ Option("l|list", []()
{
- id = stoul(s);
+ s_opts.print_list = true;
}),
- Option("p", [&](string s)
+ Option("m|modes", []()
{
- opts.print_props = true;
+ s_opts.print_modes = true;
}),
- Option("m", [&](string s)
+ Option("p|props", []()
{
- opts.print_modes = true;
+ s_opts.print_props = true;
}),
- Option("r", [&](string s)
- {
- opts.recurse = true;
+ Option("|xmode", []() {
+ s_opts.x_modeline = true;
}),
- Option("h|help", [&]()
+ Option("h|help", []()
{
usage();
exit(-1);
@@ -186,36 +521,15 @@ int main(int argc, char **argv)
exit(-1);
}
- Card card;
-
- /* No options impliles recursion */
- if (id == 0) {
- opts.recurse = true;
- for (auto conn : card.get_connectors())
- print_connector(*conn, 0);
- return 0;
- } else {
- auto ob = card.get_object(id);
- if (!ob) {
- cerr << "kmsprint" << ": Object id " <<
- id << " not found." << endl;
- return -1;
- }
-
- if (auto co = dynamic_cast<Connector*>(ob))
- print_connector(*co, 0);
- else if (auto en = dynamic_cast<Encoder*>(ob))
- print_encoder(*en, 0);
- else if (auto cr = dynamic_cast<Crtc*>(ob))
- print_crtc(*cr, 0);
- else if (auto pl = dynamic_cast<Plane*>(ob))
- print_plane(*pl, 0);
- else {
- cerr << "kmsprint" << ": Unkown DRM Object type" <<
- endl;
- return -1;
- }
+ Card card(dev_path);
+ if (s_opts.print_modes) {
+ print_modes(card);
return 0;
}
+
+ if (s_opts.print_list)
+ print_as_list(card);
+ else
+ print_as_tree(card);
}