summaryrefslogtreecommitdiff
path: root/kmscube.c
diff options
context:
space:
mode:
Diffstat (limited to 'kmscube.c')
-rw-r--r--kmscube.c155
1 files changed, 136 insertions, 19 deletions
diff --git a/kmscube.c b/kmscube.c
index fb4e2ef..99d9d84 100644
--- a/kmscube.c
+++ b/kmscube.c
@@ -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);
}