diff options
Diffstat (limited to 'kmscube.c')
-rw-r--r-- | kmscube.c | 155 |
1 files changed, 136 insertions, 19 deletions
@@ -30,6 +30,8 @@ #include <stdio.h> #include <getopt.h> #include <pthread.h> +#include <xcb/xcb.h> +#include <xcb/randr.h> #include "common.h" #include "drm-common.h" @@ -37,7 +39,7 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -static const char shortopts[] = "ArD:M:"; +static const char shortopts[] = "ArD:M:l"; static enum mode mode = SMOOTH; static int atomic = 0; @@ -47,6 +49,7 @@ static const struct option longopts[] = { {"device", required_argument, 0, 'D'}, {"mode", required_argument, 0, 'M'}, {"thread", no_argument, 0, 't'}, + {"lease", no_argument, 0, 'l'}, {0, 0, 0, 0} }; @@ -58,6 +61,7 @@ static void usage(const char *name) " -A, --atomic use atomic modesetting and fencing\n" " -D, --device=DEVICE use the given device\n" " -t, --thread two threads and cubes on two monitors\n" + " -l, --lease lease output from the X server\n" " -M, --mode=MODE specify mode, one of:\n" " smooth - smooth shaded cube (default)\n" " rgba - rgba textured cube\n" @@ -90,16 +94,16 @@ static void dump_objects(char *head, drmModeObjectListPtr objects) { printf("\n"); } -int run(int fd) { +int run(int fd, int nfd) { struct egl *egl; struct gbm *gbm; struct drm *drm; int ret; if (atomic) - drm = init_drm_atomic(fd); + drm = init_drm_atomic(fd, nfd); else - drm = init_drm_legacy(fd); + drm = init_drm_legacy(fd, nfd); if (!drm) { printf("failed to initialize %s DRM\n", atomic ? "atomic" : "legacy"); return -1; @@ -137,7 +141,7 @@ static void *thread_run(void *arg) printf("child on fd %d\n", fd); printf("child running now...\n"); - run(fd); + run(fd, -1); return 0; } @@ -145,8 +149,10 @@ int main(int argc, char *argv[]) { const char *device = "/dev/dri/card0"; int do_thread = 0; + int do_lease = 0; int opt; int fd; + int nfd = -1; while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) != -1) { switch (opt) { @@ -174,29 +180,140 @@ int main(int argc, char *argv[]) case 't': do_thread = 1; break; + case 'l': + do_lease = 1; + break; default: usage(argv[0]); return -1; } } - fd = open(device, O_RDWR); - if (fd < 0) { - printf("could not open drm device\n"); - return -1; + if (do_lease) { + xcb_connection_t *connection; + int screen; + + connection = xcb_connect(NULL, &screen); + if (!connection) { + printf("Connection to X server failed\n"); + exit(1); + } + xcb_randr_query_version_cookie_t rqv_c = xcb_randr_query_version(connection, + XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION); + xcb_randr_query_version_reply_t *rqv_r = xcb_randr_query_version_reply(connection, rqv_c, NULL); + + if (!rqv_r || rqv_r->minor_version < 6) { + printf("No new-enough RandR version\n"); + exit(1); + } + + xcb_screen_iterator_t s_i; + + int i_s = 0; + + for (s_i = xcb_setup_roots_iterator(xcb_get_setup(connection)); + s_i.rem; + xcb_screen_next(&s_i), i_s++) { + printf ("index %d screen %d\n", s_i.index, screen); + if (i_s == screen) + break; + } + + xcb_window_t root = s_i.data->root; + + printf("root %x\n", root); + + xcb_randr_get_screen_resources_cookie_t gsr_c = xcb_randr_get_screen_resources(connection, root); + + xcb_randr_get_screen_resources_reply_t *gsr_r = xcb_randr_get_screen_resources_reply(connection, gsr_c, NULL); + + if (!gsr_r) { + printf("get_screen_resources failed\n"); + exit(1); + } + + xcb_randr_output_t *ro = xcb_randr_get_screen_resources_outputs(gsr_r); + int o, c; + + xcb_randr_output_t output = 0; + + /* Find a connected but idle output */ + for (o = 0; output == 0 && o < gsr_r->num_outputs; o++) { + xcb_randr_get_output_info_cookie_t goi_c = xcb_randr_get_output_info(connection, ro[o], gsr_r->config_timestamp); + + xcb_randr_get_output_info_reply_t *goi_r = xcb_randr_get_output_info_reply(connection, goi_c, NULL); + + /* Find the first connected but unused output */ + if (goi_r->connection == XCB_RANDR_CONNECTION_CONNECTED && + goi_r->crtc == 0) { + output = ro[o]; + } + + free(goi_r); + } + + xcb_randr_crtc_t *rc = xcb_randr_get_screen_resources_crtcs(gsr_r); + + xcb_randr_crtc_t crtc = 0; + + /* Find an idle crtc */ + for (c = 0; crtc == 0 && c < gsr_r->num_crtcs; c++) { + xcb_randr_get_crtc_info_cookie_t gci_c = xcb_randr_get_crtc_info(connection, rc[c], gsr_r->config_timestamp); + + xcb_randr_get_crtc_info_reply_t *gci_r = xcb_randr_get_crtc_info_reply(connection, gci_c, NULL); + + /* Find the first connected but unused crtc */ + if (gci_r->mode == 0) + crtc = rc[c]; + + free(gci_r); + } + + free(gsr_r); + + printf("output %x crtc %x\n", output, crtc); + + xcb_randr_lease_t lease = xcb_generate_id(connection); + + xcb_randr_create_lease_cookie_t rcl_c = xcb_randr_create_lease(connection, + root, + lease, + 1, + 1, + &crtc, + &output); + xcb_randr_create_lease_reply_t *rcl_r = xcb_randr_create_lease_reply(connection, rcl_c, NULL); + + if (!rcl_r) { + printf("create_lease failed\n"); + exit(1); + } + + int *rcl_f = xcb_randr_create_lease_reply_fds(connection, rcl_r); + + fd = rcl_f[0]; + + printf("fd %d\n", fd); + + } else { + fd = open(device, O_RDWR); + if (fd < 0) { + printf("could not open drm device\n"); + return -1; + } } if (do_thread) { struct drm_resources resources; uint32_t objects[3]; int nobjects; - int nfd; uint32_t lessee; pthread_t thread; drmModeLesseeListPtr l_list; drmModeObjectListPtr o_list; - if (find_drm(&resources, fd) != 0) { + if (find_drm(&resources, fd, -1) != 0) { printf("Could not get DRM resources for fork\n"); return -1; } @@ -211,36 +328,36 @@ int main(int argc, char *argv[]) if (resources.crtc) objects[nobjects++] = resources.crtc; - o_list = drmModeGetLease(fd, 0); + o_list = drmModeGetLease(fd); dump_objects("owner before lease", o_list); free(o_list); - l_list = drmModeListLessees(fd, 0); + l_list = drmModeListLessees(fd); dump_lessees("owner before lease", l_list); free(l_list); - nfd = drmModeCreateLease(fd, objects, nobjects, 0, 1, &lessee); + nfd = drmModeCreateLease(fd, objects, nobjects, 0, &lessee); - o_list = drmModeGetLease(fd, 0); + o_list = drmModeGetLease(fd); dump_objects("owner after lease", o_list); free(o_list); - l_list = drmModeListLessees(fd, 0); + l_list = drmModeListLessees(fd); dump_lessees("owner after lease", l_list); free(l_list); - o_list = drmModeGetLease(nfd, lessee); + o_list = drmModeGetLease(nfd); dump_objects("lessee after lease", o_list); free(o_list); - l_list = drmModeListLessees(nfd, lessee); + l_list = drmModeListLessees(nfd); dump_lessees("lessee after lease", l_list); @@ -259,5 +376,5 @@ int main(int argc, char *argv[]) printf("parent running now...\n"); } - return run(fd); + return run(fd, nfd); } |