diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2019-06-14 10:05:50 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2019-06-14 10:05:50 +0200 |
commit | ac3a01bfe9520e61f44e7f9893145d82b53522ae (patch) | |
tree | 821b1f519438e1f486dfae5045070e7d7983e1c5 | |
parent | e7580760b355347220993ae485d3e8962e14e77e (diff) | |
download | drminfo-ac3a01bfe9520e61f44e7f9893145d82b53522ae.tar.gz |
add drm lease support to drmtest
-rw-r--r-- | drm-lease-x11.c | 245 | ||||
-rw-r--r-- | drm-lease.c | 21 | ||||
-rw-r--r-- | drm-lease.h | 2 | ||||
-rw-r--r-- | drminfo.spec | 2 | ||||
-rw-r--r-- | drmtest.c | 28 | ||||
-rw-r--r-- | drmtools.c | 13 | ||||
-rw-r--r-- | drmtools.h | 3 | ||||
-rw-r--r-- | egltest.c | 2 | ||||
-rw-r--r-- | meson.build | 12 | ||||
-rw-r--r-- | virtiotest.c | 2 |
10 files changed, 310 insertions, 20 deletions
diff --git a/drm-lease-x11.c b/drm-lease-x11.c new file mode 100644 index 0000000..e0a9c3e --- /dev/null +++ b/drm-lease-x11.c @@ -0,0 +1,245 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "drm-lease.h" + +#ifdef HAVE_XRANDR + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +#include <X11/X.h> +#include <xcb/randr.h> + +typedef struct xserver_t { + xcb_connection_t *conn; + xcb_window_t root; + + const xcb_query_extension_reply_t *ext_r; + + xcb_randr_output_t randr_output; + xcb_randr_crtc_t randr_crtc; + xcb_randr_lease_t randr_lease; + xcb_randr_mode_info_t randr_mode; + xcb_randr_get_screen_resources_reply_t *gsr_r; +} xserver_t; + +static const char *core_err[] = { + [Success] = "Success", + [BadRequest] = "BadRequest", + [BadValue] = "BadValue", + [BadWindow] = "BadWindow", + [BadPixmap] = "BadPixmap", + [BadAtom] = "BadAtom", + [BadCursor] = "BadCursor", + [BadFont] = "BadFont", + [BadMatch] = "BadMatch", + [BadDrawable] = "BadDrawable", + [BadAccess] = "BadAccess", + [BadAlloc] = "BadAlloc", + [BadColor] = "BadColor", + [BadGC] = "BadGC", + [BadIDChoice] = "BadIDChoice", + [BadName] = "BadName", + [BadLength] = "BadLength", + [BadImplementation] = "BadImplementation", +}; + +static const char *xrandr_err[] = { + [XCB_RANDR_BAD_OUTPUT] = "BadOutput", + [XCB_RANDR_BAD_CRTC] = "BadCRTC", + [XCB_RANDR_BAD_MODE] = "BadMode", + [XCB_RANDR_BAD_PROVIDER] = "BadProvider", +}; + +static void xserver_print_error(xserver_t *x, + xcb_generic_error_t *error) +{ + const char *name; + + if (error->error_code >= x->ext_r->first_error && + error->error_code < x->ext_r->first_error + ARRAY_SIZE(xrandr_err)) { + name = xrandr_err[error->error_code - x->ext_r->first_error]; + } else if (error->error_code < ARRAY_SIZE(core_err)) { + name = core_err[error->error_code]; + } else { + name = "unknown"; + } + fprintf(stderr, "%s (code %d, op %d:%d)\n", name, error->error_code, + error->major_code, error->minor_code); +} + +static xcb_randr_output_t xserver_find_output(xserver_t *x, + const char *output_name) +{ + xcb_randr_get_output_info_cookie_t goi_c; + xcb_randr_get_output_info_reply_t *goi_r; + xcb_randr_output_t output = XCB_NONE; + xcb_randr_output_t *ro; + char *name; + int o, len; + + ro = xcb_randr_get_screen_resources_outputs(x->gsr_r); + for (o = 0; o < x->gsr_r->num_outputs; o++) { + goi_c = xcb_randr_get_output_info(x->conn, ro[o], x->gsr_r->config_timestamp); + goi_r = xcb_randr_get_output_info_reply(x->conn, goi_c, NULL); + name = (char*)xcb_randr_get_output_info_name(goi_r); + len = xcb_randr_get_output_info_name_length(goi_r); + if (output_name == NULL || strncmp(name, output_name, len) == 0) { + output = ro[o]; + } + free(goi_r); + } + return output; +} + +static xcb_randr_crtc_t xserver_find_crtc(xserver_t *x, xcb_randr_output_t output) +{ + xcb_randr_crtc_t *rc = xcb_randr_get_screen_resources_crtcs(x->gsr_r); + xcb_randr_get_crtc_info_cookie_t gci_c; + xcb_randr_get_crtc_info_reply_t *gci_r; + int c; + + for (c = 0; c < x->gsr_r->num_crtcs; c++) { + gci_c = xcb_randr_get_crtc_info(x->conn, rc[c], x->gsr_r->config_timestamp); + gci_r = xcb_randr_get_crtc_info_reply(x->conn, gci_c, NULL); + if (gci_r->mode) { + int num_outputs = xcb_randr_get_crtc_info_outputs_length(gci_r); + xcb_randr_output_t *outputs = xcb_randr_get_crtc_info_outputs(gci_r); + if (num_outputs == 1 && outputs[0] == output) { + return rc[c]; + } + } else { + int num_possible = xcb_randr_get_crtc_info_possible_length(gci_r); + xcb_randr_output_t *possible = xcb_randr_get_crtc_info_possible(gci_r); + for (int p = 0; p < num_possible; p++) { + if (possible[p] == output) { + return rc[c]; + } + } + } + free(gci_r); + } + return XCB_NONE; +} + +static void xserver_lease_setup(xserver_t *x, const char *output_name) +{ + const xcb_setup_t *setup; + xcb_screen_iterator_t iter; + xcb_generic_error_t *error; + xcb_randr_query_version_cookie_t ver_c; + xcb_randr_query_version_reply_t *ver_r; + xcb_randr_get_screen_resources_cookie_t gsr_c; + xcb_randr_output_t output; + xcb_randr_crtc_t crtc; + int screen; + + x->conn = xcb_connect(NULL, &screen); + if (!x->conn) { + fprintf(stderr, "drm-lease: can not connect to X server\n"); + exit(1); + } + + /* find root window */ + setup = xcb_get_setup(x->conn); + for (iter = xcb_setup_roots_iterator(setup); iter.rem; xcb_screen_next(&iter)) { + if (screen == 0) { + x->root = iter.data->root; + break; + } + screen--; + } + + /* check for xrandr extension */ + x->ext_r = xcb_get_extension_data(x->conn, &xcb_randr_id); + if (!x->ext_r->present) { + fprintf(stderr, "drm-lease: xrandr extension not present\n"); + exit(1); + } + + ver_c = xcb_randr_query_version(x->conn, + XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION); + ver_r = xcb_randr_query_version_reply(x->conn, ver_c, &error); + if (!ver_r) { + fprintf(stderr, "drm-lease: xrandr version query error\n"); + exit(1); + } + fprintf(stderr, "drm-lease: xrandr: client v%d.%x, server v%d.%x\n", + XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION, + ver_r->major_version, ver_r->minor_version); + free(ver_r); + + /* Get RandR resources */ + gsr_c = xcb_randr_get_screen_resources(x->conn, x->root); + x->gsr_r = xcb_randr_get_screen_resources_reply(x->conn, gsr_c, &error); + if (!x->gsr_r) { + fprintf(stderr, "drm-lease: xrandr: can not get screen resources\n"); + exit(1); + } + + output = xserver_find_output(x, output_name); + if (output == XCB_NONE) { + fprintf(stderr, "drm-lease: xrandr: no output found\n"); + exit(1); + } + fprintf(stderr, "drm-lease: xrandr: using output 0x%x\n", output); + + crtc = xserver_find_crtc(x, output); + if (crtc == XCB_NONE) { + fprintf(stderr, "drm-lease: xrandr: crtc not found\n"); + exit(1); + } + fprintf(stderr, "drm-lease: xrandr: using crtc 0x%x\n", crtc); + + /* Generate RandR lease id */ + x->randr_lease = xcb_generate_id(x->conn); + x->randr_output = output; + x->randr_crtc = crtc; +} + +static int xserver_make_lease(xserver_t *x) +{ + xcb_randr_create_lease_cookie_t cl_c; + xcb_randr_create_lease_reply_t *cl_r; + xcb_generic_error_t *error; + int *rcl_f; + int fd = -1; + + cl_c = xcb_randr_create_lease(x->conn, x->root, + x->randr_lease, + 1, 1, + &x->randr_crtc, + &x->randr_output); + cl_r = xcb_randr_create_lease_reply(x->conn, cl_c, &error); + if (!cl_r) { + fprintf(stderr, "drm-lease: xrandr: create lease failed: "); + xserver_print_error(x, error); + exit(1); + } + + if (cl_r->nfd > 0) { + rcl_f = xcb_randr_create_lease_reply_fds(x->conn, cl_r); + fd = rcl_f[0]; + } + free (cl_r); + + if (fd < 0) { + fprintf(stderr, "drm-lease: xrandr: lease returned invalid fd\n"); + exit(1); + } + + return fd; +} + +int drm_lease_xserver(const char *output) +{ + xserver_t *x = malloc(sizeof(xserver_t)); + + xserver_lease_setup(x, output); + return xserver_make_lease(x); +} + +#endif /* HAVE_XRANDR */ diff --git a/drm-lease.c b/drm-lease.c new file mode 100644 index 0000000..881bba2 --- /dev/null +++ b/drm-lease.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "drm-lease.h" + +int drm_lease(const char *output) +{ + if (getenv("DISPLAY") != NULL) { +#ifdef HAVE_XRANDR + return drm_lease_xserver(output); +#else + fprintf(stderr, "drm-lease: compiled without xrandr support.\n"); + exit(1); +#endif + } + + fprintf(stderr, "drm-lease: don't know where to lease from.\n"); + exit(1); +} diff --git a/drm-lease.h b/drm-lease.h new file mode 100644 index 0000000..e28bc2d --- /dev/null +++ b/drm-lease.h @@ -0,0 +1,2 @@ +int drm_lease(const char *output); +int drm_lease_xserver(const char *output); diff --git a/drminfo.spec b/drminfo.spec index b17a8e8..0d2a826 100644 --- a/drminfo.spec +++ b/drminfo.spec @@ -18,6 +18,8 @@ BuildRequires: pkgconfig(cairo) BuildRequires: pkgconfig(pixman-1) BuildRequires: pkgconfig(gtk+-3.0) BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(xcb) +BuildRequires: pkgconfig(xcb-randr) %description drminfo - print drm device props @@ -24,6 +24,7 @@ #include "ttytools.h" #include "logind.h" #include "drmtools.h" +#include "drm-lease.h" #include "render.h" #include "image.h" @@ -183,15 +184,16 @@ static void usage(FILE *fp) "usage: drmtest [ options ]\n" "\n" "options:\n" - " -h print this\n" - " -p pixman mode\n" - " -a autotest mode (don't print hardware info)\n" - " -c <nr> pick card\n" - " -o <name> pick output\n" - " -s <secs> set sleep time (default: 60)\n" - " -i <file> load and display image <file>\n" - " -f <fmt> pick framebuffer format\n" - " -m <mode> pick video mode format\n" + " -h print this\n" + " -p pixman mode\n" + " -a autotest mode (don't print hardware info)\n" + " -c <nr> pick card\n" + " -o <name> pick output\n" + " -s <secs> set sleep time (default: 60)\n" + " -i <file> load and display image <file>\n" + " -f <fmt> pick framebuffer format\n" + " -m <mode> pick video mode format\n" + " -L <output> get a drm lease for output\n" "\n"); } @@ -199,6 +201,7 @@ int main(int argc, char **argv) { int card = 0; int secs = 60; + int lease_fd = -1; char *output = NULL; char *format = NULL; char *modename = NULL; @@ -208,7 +211,7 @@ int main(int argc, char **argv) int c,i; for (;;) { - c = getopt(argc, argv, "hpac:s:o:i:f:m:"); + c = getopt(argc, argv, "hpaL:c:s:o:i:f:m:"); if (c == -1) break; switch (c) { @@ -236,6 +239,9 @@ int main(int argc, char **argv) case 'm': modename = optarg; break; + case 'L': + lease_fd = drm_lease(optarg); + break; case 'h': usage(stdout); exit(0); @@ -268,7 +274,7 @@ int main(int argc, char **argv) } logind_init(); - drm_init_dev(card, output, modename, false); + drm_init_dev(card, output, modename, false, lease_fd); if (!fmt) { /* find first supported in list */ @@ -715,7 +715,8 @@ drmVersion *version = NULL; static drmModeCrtc *scrtc = NULL; void drm_init_dev(int devnr, const char *output, - const char *modename, bool need_dumb) + const char *modename, bool need_dumb, + int lease_fd) { drmModeRes *res; char dev[64]; @@ -724,9 +725,13 @@ void drm_init_dev(int devnr, const char *output, int i, rc; uint64_t has_dumb; - /* open device */ - snprintf(dev, sizeof(dev), DRM_DEV_NAME, DRM_DIR_NAME, devnr); - drm_fd = device_open(dev); + if (lease_fd >= 0) { + drm_fd = lease_fd; + } else { + /* open device */ + snprintf(dev, sizeof(dev), DRM_DEV_NAME, DRM_DIR_NAME, devnr); + drm_fd = device_open(dev); + } version = drmGetVersion(drm_fd); if (need_dumb) { @@ -42,7 +42,8 @@ extern drmModeEncoder *drm_enc; extern drmVersion *version; void drm_init_dev(int devnr, const char *output, - const char *modename, bool need_dumb); + const char *modename, bool need_dumb, + int lease_fd); void drm_fini_dev(void); void drm_show_fb(void); @@ -124,7 +124,7 @@ int main(int argc, char **argv) } logind_init(); - drm_init_dev(card, output, modename, false); + drm_init_dev(card, output, modename, false, -1); drm_setup_egl(); if (printinfo) diff --git a/meson.build b/meson.build index ff44250..e1d62e0 100644 --- a/meson.build +++ b/meson.build @@ -11,6 +11,8 @@ epoxy_dep = dependency('epoxy') cairo_dep = dependency('cairo') pixman_dep = dependency('pixman-1') gtk3_dep = dependency('gtk+-3.0') +xcb_dep = dependency('xcb', required : false) +randr_dep = dependency('xcb-randr', required : false, version : '>=1.13') systemd_dep = dependency('libsystemd', required : false, version : '>=221') # configuration @@ -18,15 +20,20 @@ config = configuration_data() if systemd_dep.found() config.set('HAVE_SYSTEMD', true) endif +if randr_dep.found() + config.set('HAVE_XRANDR', true) +endif configure_file(output : 'config.h', configuration : config) # libjpeg dep jpeg_dep = declare_dependency(link_args : '-ljpeg') drminfo_srcs = [ 'drminfo.c', 'drmtools.c', 'logind.c' ] -drmtest_srcs = [ 'drmtest.c', 'drmtools.c', 'logind.c', 'ttytools.c', 'render.c', 'image.c' ] +drmtest_srcs = [ 'drmtest.c', 'drmtools.c', 'drm-lease.c', 'drm-lease-x11.c', + 'logind.c', 'ttytools.c', 'render.c', 'image.c' ] fbinfo_srcs = [ 'fbinfo.c', 'fbtools.c', 'logind.c' ] -fbtest_srcs = [ 'fbtest.c', 'fbtools.c', 'logind.c' , 'ttytools.c', 'render.c', 'image.c' ] +fbtest_srcs = [ 'fbtest.c', 'fbtools.c', 'logind.c', + 'ttytools.c', 'render.c', 'image.c' ] prime_srcs = [ 'prime.c', 'logind.c' ] viotest_srcs = [ 'virtiotest.c', 'drmtools.c', 'logind.c', 'ttytools.c', 'render.c' ] egltest_srcs = [ 'egltest.c', 'drmtools.c', 'drmtools-egl.c', 'logind.c', 'ttytools.c' ] @@ -34,6 +41,7 @@ gtktest_srcs = [ 'gtktest.c', 'render.c', 'image.c' ] drminfo_deps = [ libdrm_dep, cairo_dep, pixman_dep, systemd_dep ] drmtest_deps = [ libdrm_dep, gbm_dep, epoxy_dep, + xcb_dep, randr_dep, cairo_dep, pixman_dep, jpeg_dep, systemd_dep ] fbinfo_deps = [ cairo_dep, systemd_dep ] fbtest_deps = [ cairo_dep, pixman_dep, jpeg_dep, systemd_dep ] diff --git a/virtiotest.c b/virtiotest.c index e108232..8acce4c 100644 --- a/virtiotest.c +++ b/virtiotest.c @@ -292,7 +292,7 @@ int main(int argc, char **argv) assert(fmt != NULL); logind_init(); - drm_init_dev(card, output, modename, false); + drm_init_dev(card, output, modename, false, -1); if (printinfo) virtio_print_caps(); |