diff --git a/utils/kmstest.cpp b/utils/kmstest.cpp
index cc895e3dde9496bec8c9ff47fa01e45b4421c582..f12ed095712614e9b2976c7e859d63b2bd0047a3 100644 (file)
--- a/utils/kmstest.cpp
+++ b/utils/kmstest.cpp
#include <kms++/kms++.h>
#include <kms++/modedb.h>
+#include <kms++/mode_cvt.h>
#include <kms++util/kms++util.h>
unsigned w;
unsigned h;
- vector<DumbFramebuffer*> fbs;
+ vector<MappedFramebuffer*> fbs;
};
struct OutputInfo
Plane* primary_plane;
Videomode mode;
bool user_set_crtc;
- vector<DumbFramebuffer*> fbs;
+ vector<MappedFramebuffer*> fbs;
vector<PlaneInfo> planes;
};
static unsigned s_num_buffers = 1;
static bool s_flip_mode;
static bool s_flip_sync;
+static bool s_cvt;
+static bool s_cvt_v2;
+static bool s_cvt_vid_opt;
static set<Crtc*> s_used_crtcs;
static set<Plane*> s_used_planes;
static void parse_crtc(Card& card, const string& crtc_str, OutputInfo& output)
{
- // @12:1920x1200@60
- const regex mode_re("(?:(@?)(\\d+):)?" // @12:
- "(?:(\\d+)x(\\d+)(i)?)" // 1920x1200i
- "(?:@([\\d\\.]+))?"); // @60
+ // @12:1920x1200i@60
+ // @12:33000000,800/210/30/16/-,480/22/13/10/-,i
+
+ const regex modename_re("(?:(@?)(\\d+):)?" // @12:
+ "(?:(\\d+)x(\\d+)(i)?)" // 1920x1200i
+ "(?:@([\\d\\.]+))?"); // @60
+
+ const regex modeline_re("(?:(@?)(\\d+):)?" // @12:
+ "(\\d+)," // 33000000,
+ "(\\d+)/(\\d+)/(\\d+)/(\\d+)/([+-])," // 800/210/30/16/-,
+ "(\\d+)/(\\d+)/(\\d+)/(\\d+)/([+-])" // 480/22/13/10/-
+ "(?:,([i]+))?" // ,i
+ );
smatch sm;
- if (!regex_match(crtc_str, sm, mode_re))
- EXIT("Failed to parse crtc option '%s'", crtc_str.c_str());
+ if (regex_match(crtc_str, sm, modename_re)) {
+ if (sm[2].matched) {
+ bool use_id = sm[1].length() == 1;
+ unsigned num = stoul(sm[2].str());
- if (sm[2].matched) {
- bool use_id = sm[1].length() == 1;
- unsigned num = stoul(sm[2].str());
+ if (use_id) {
+ Crtc* c = card.get_crtc(num);
+ if (!c)
+ EXIT("Bad crtc id '%u'", num);
- if (use_id) {
- Crtc* c = card.get_crtc(num);
- if (!c)
- EXIT("Bad crtc id '%u'", num);
+ output.crtc = c;
+ } else {
+ auto crtcs = card.get_crtcs();
- output.crtc = c;
- } else {
- auto crtcs = card.get_crtcs();
+ if (num >= crtcs.size())
+ EXIT("Bad crtc number '%u'", num);
- if (num >= crtcs.size())
- EXIT("Bad crtc number '%u'", num);
+ output.crtc = crtcs[num];
+ }
+ } else {
+ output.crtc = output.connector->get_current_crtc();
+ }
- output.crtc = crtcs[num];
+ unsigned w = stoul(sm[3]);
+ unsigned h = stoul(sm[4]);
+ bool ilace = sm[5].matched ? true : false;
+ float refresh = sm[6].matched ? stof(sm[6]) : 0;
+
+ if (s_cvt) {
+ output.mode = videomode_from_cvt(w, h, refresh, ilace, s_cvt_v2, s_cvt_vid_opt);
+ } else if (s_use_dmt) {
+ try {
+ output.mode = find_dmt(w, h, refresh, ilace);
+ } catch (exception& e) {
+ EXIT("Mode not found from DMT tables\n");
+ }
+ } else if (s_use_cea) {
+ try {
+ output.mode = find_cea(w, h, refresh, ilace);
+ } catch (exception& e) {
+ EXIT("Mode not found from CEA tables\n");
+ }
+ } else {
+ try {
+ output.mode = output.connector->get_mode(w, h, refresh, ilace);
+ } catch (exception& e) {
+ EXIT("Mode not found from the connector\n");
+ }
}
- } else {
- output.crtc = output.connector->get_current_crtc();
- }
+ } else if (regex_match(crtc_str, sm, modeline_re)) {
+ if (sm[2].matched) {
+ bool use_id = sm[1].length() == 1;
+ unsigned num = stoul(sm[2].str());
- unsigned w = stoul(sm[3]);
- unsigned h = stoul(sm[4]);
- bool ilace = sm[5].matched ? true : false;
- float refresh = sm[6].matched ? stof(sm[6]) : 0;
+ if (use_id) {
+ Crtc* c = card.get_crtc(num);
+ if (!c)
+ EXIT("Bad crtc id '%u'", num);
- bool found_mode = false;
+ output.crtc = c;
+ } else {
+ auto crtcs = card.get_crtcs();
- try {
- output.mode = output.connector->get_mode(w, h, refresh, ilace);
- found_mode = true;
- } catch (exception& e) { }
+ if (num >= crtcs.size())
+ EXIT("Bad crtc number '%u'", num);
- if (!found_mode && s_use_dmt) {
- try {
- output.mode = find_dmt(w, h, refresh, ilace);
- found_mode = true;
- printf("Found mode from DMT\n");
- } catch (exception& e) { }
- }
+ output.crtc = crtcs[num];
+ }
+ } else {
+ output.crtc = output.connector->get_current_crtc();
+ }
- if (!found_mode && s_use_cea) {
- try {
- output.mode = find_cea(w, h, refresh, ilace);
- found_mode = true;
- printf("Found mode from CEA\n");
- } catch (exception& e) { }
+ unsigned clock = stoul(sm[3]);
+
+ unsigned hact = stoul(sm[4]);
+ unsigned hfp = stoul(sm[5]);
+ unsigned hsw = stoul(sm[6]);
+ unsigned hbp = stoul(sm[7]);
+ bool h_pos_sync = sm[8] == "+" ? true : false;
+
+ unsigned vact = stoul(sm[9]);
+ unsigned vfp = stoul(sm[10]);
+ unsigned vsw = stoul(sm[11]);
+ unsigned vbp = stoul(sm[12]);
+ bool v_pos_sync = sm[13] == "+" ? true : false;
+
+ output.mode = videomode_from_timings(clock / 1000, hact, hfp, hsw, hbp, vact, vfp, vsw, vbp);
+ output.mode.set_hsync(h_pos_sync ? SyncPolarity::Positive : SyncPolarity::Negative);
+ output.mode.set_vsync(v_pos_sync ? SyncPolarity::Positive : SyncPolarity::Negative);
+
+ if (sm[14].matched) {
+ for (int i = 0; i < sm[14].length(); ++i) {
+ char f = string(sm[14])[i];
+
+ switch (f) {
+ case 'i':
+ output.mode.set_interlace(true);
+ break;
+ default:
+ EXIT("Bad mode flag %c", f);
+ }
+ }
+ }
+ } else {
+ EXIT("Failed to parse crtc option '%s'", crtc_str.c_str());
}
-
- if (!found_mode)
- throw invalid_argument("Mode not found");
}
static void parse_plane(Card& card, const string& plane_str, const OutputInfo& output, PlaneInfo& pinfo)
@@ -224,9 +288,9 @@ static void parse_plane(Card& card, const string& plane_str, const OutputInfo& o
pinfo.y = output.mode.vdisplay / 2 - pinfo.h / 2;
}
-static vector<DumbFramebuffer*> get_default_fb(Card& card, unsigned width, unsigned height)
+static vector<MappedFramebuffer*> get_default_fb(Card& card, unsigned width, unsigned height)
{
- vector<DumbFramebuffer*> v;
+ vector<MappedFramebuffer*> v;
for (unsigned i = 0; i < s_num_buffers; ++i)
v.push_back(new DumbFramebuffer(card, width, height, PixelFormat::XRGB8888));
@@ -234,7 +298,7 @@ static vector<DumbFramebuffer*> get_default_fb(Card& card, unsigned width, unsig
return v;
}
-static vector<DumbFramebuffer*> parse_fb(Card& card, const string& fb_str, unsigned def_w, unsigned def_h)
+static vector<MappedFramebuffer*> parse_fb(Card& card, const string& fb_str, unsigned def_w, unsigned def_h)
{
unsigned w = def_w;
unsigned h = def_h;
@@ -259,7 +323,7 @@ static vector<DumbFramebuffer*> parse_fb(Card& card, const string& fb_str, unsig
format = FourCCToPixelFormat(sm[3]);
}
- vector<DumbFramebuffer*> v;
+ vector<MappedFramebuffer*> v;
for (unsigned i = 0; i < s_num_buffers; ++i)
v.push_back(new DumbFramebuffer(card, w, h, format));
" --device=DEVICE DEVICE is the path to DRM card to open\n"
" -c, --connector=CONN CONN is <connector>\n"
" -r, --crtc=CRTC CRTC is [<crtc>:]<w>x<h>[@<Hz>]\n"
+ " or\n"
+ " [<crtc>:]<pclk>,<hact>/<hfp>/<hsw>/<hbp>/<hsp>,<vact>/<vfp>/<vsw>/<vbp>/<vsp>[,i]\n"
" -p, --plane=PLANE PLANE is [<plane>:][<x>,<y>-]<w>x<h>\n"
" -f, --fb=FB FB is [<w>x<h>][-][<4cc>]\n"
" --dmt Search for the given mode from DMT tables\n"
" --cea Search for the given mode from CEA tables\n"
+ " --cvt=CVT Create videomode with CVT. CVT is 'v1', 'v2' or 'v2o'\n"
" --flip Do page flipping for each output\n"
" --sync Synchronize page flipping\n"
"\n"
{
s_flip_sync = true;
}),
+ Option("|cvt=", [&](string s)
+ {
+ if (s == "v1")
+ s_cvt = true;
+ else if (s == "v2")
+ s_cvt = s_cvt_v2 = true;
+ else if (s == "v2o")
+ s_cvt = s_cvt_v2 = s_cvt_vid_opt = true;
+ else {
+ usage();
+ exit(-1);
+ }
+ }),
Option("h|help", [&]()
{
usage();
@@ -497,7 +577,7 @@ static vector<OutputInfo> setups_to_outputs(Card& card, const vector<Arg>& outpu
// create default framebuffers if needed
for (OutputInfo& o : outputs) {
if (!o.crtc) {
- get_default_crtc(card, *current_output);
+ get_default_crtc(card, o);
o.user_set_crtc = true;
}
auto conn = o.connector;
auto crtc = o.crtc;
- if (!o.fbs.empty()) {
- auto fb = o.fbs[0];
+ blobs.emplace_back(o.mode.to_blob(card));
+ Blob* mode_blob = blobs.back().get();
- blobs.emplace_back(o.mode.to_blob(card));
- Blob* mode_blob = blobs.back().get();
+ req.add(conn, {
+ { "CRTC_ID", crtc->id() },
+ });
- req.add(conn, {
- { "CRTC_ID", crtc->id() },
- });
+ req.add(crtc, {
+ { "ACTIVE", 1 },
+ { "MODE_ID", mode_blob->id() },
+ });
- req.add(crtc, {
- { "ACTIVE", 1 },
- { "MODE_ID", mode_blob->id() },
- });
+ if (!o.fbs.empty()) {
+ auto fb = o.fbs[0];
req.add(o.primary_plane, {
{ "FB_ID", fb->id() },
queue_next();
}
- static unsigned get_bar_pos(DumbFramebuffer* fb, unsigned frame_num)
+ static unsigned get_bar_pos(MappedFramebuffer* fb, unsigned frame_num)
{
return (frame_num * bar_speed) % (fb->width() - bar_width + 1);
}
- static void draw_bar(DumbFramebuffer* fb, unsigned frame_num)
+ static void draw_bar(MappedFramebuffer* fb, unsigned frame_num)
{
int old_xpos = frame_num < s_num_buffers ? -1 : get_bar_pos(fb, frame_num - s_num_buffers);
int new_xpos = get_bar_pos(fb, frame_num);
vector<OutputInfo> outputs = setups_to_outputs(card, output_args);
+ ResourceManager resman(card);
+
if (card.has_atomic()) {
for (OutputInfo& o : outputs) {
- o.primary_plane = o.crtc->get_primary_plane();
+ o.primary_plane = resman.reserve_primary_plane(o.crtc);
if (!o.fbs.empty() && !o.primary_plane)
EXIT("Could not get primary plane for crtc '%u'", o.crtc->id());