diff --git a/src/instance.c b/src/instance.c index 09d62e5..6878ae8 100644 --- a/src/instance.c +++ b/src/instance.c @@ -193,19 +193,26 @@ static int drm_find_psvr_xcb(Instance * instance) return(0); } + const xcb_setup_t *setup = xcb_get_setup(instance->connection); + + int screen = instance->screen; + + xcb_window_t root = 0; + xcb_screen_iterator_t s_i; int i_s = 0; - for (s_i = xcb_setup_roots_iterator(xcb_get_setup(instance->connection)); s_i.rem; xcb_screen_next(&s_i), i_s++) + for (s_i = xcb_setup_roots_iterator(setup); s_i.rem; xcb_screen_next(&s_i), i_s++) { printf ("index %d screen %d\n", s_i.index, instance->screen); - if (i_s == instance->screen) - break; + if (screen == 0) { + root = s_i.data->root; + break; + } + --screen; } - 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(instance->connection, root); @@ -218,44 +225,90 @@ static int drm_find_psvr_xcb(Instance * instance) return(0); } + xcb_timestamp_t config_timestamp = gsr_r->config_timestamp; + xcb_randr_output_t *ro = xcb_randr_get_screen_resources_outputs(gsr_r); int o, c; + int num_outputs = gsr_r->num_outputs; + xcb_randr_output_t output = 0; + char * output_name = NULL; + /* 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(instance->connection, ro[o], gsr_r->config_timestamp); + for (o = 0; o < num_outputs; o++) { + xcb_randr_get_output_info_cookie_t goi_c = xcb_randr_get_output_info(instance->connection, ro[o], config_timestamp); xcb_randr_get_output_info_reply_t *goi_r = xcb_randr_get_output_info_reply(instance->connection, goi_c, NULL); + output_name = xcb_randr_get_output_info_name(goi_r); + /* Find the first connected but unused output */ if (goi_r->connection == XCB_RANDR_CONNECTION_CONNECTED && goi_r->crtc == 0) { output = ro[o]; + break; } free(goi_r); } + if (!output) + { + fprintf(stderr, "no free output found\n"); + return 0; + } + xcb_randr_crtc_t *rc = xcb_randr_get_screen_resources_crtcs(gsr_r); xcb_randr_crtc_t crtc = 0; - /* Find an idle crtc */ + xcb_randr_crtc_t idle_crtc = XCB_NONE; + xcb_randr_crtc_t active_crtc = XCB_NONE; + + /* Find either a crtc already connected to the desired output or idle */ 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(instance->connection, rc[c], gsr_r->config_timestamp); xcb_randr_get_crtc_info_reply_t *gci_r = xcb_randr_get_crtc_info_reply(instance->connection, gci_c, NULL); /* Find the first connected but unused crtc */ - if (gci_r->mode == 0) - crtc = rc[c]; + + 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); + for (int o = 0; o < num_outputs; o++) + if (outputs[o] == output && num_outputs == 1) { + active_crtc = rc[c]; + break; + } + + } else if (idle_crtc == 0) { + 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) { + idle_crtc = rc[c]; + break; + } + } free(gci_r); } - free(gsr_r); + if (active_crtc) + crtc = active_crtc; + else + crtc = idle_crtc; + +// free(gsr_r); + + if (crtc == XCB_NONE) + { + fprintf(stderr, "cannot find usable CRTC\n"); + return 0; + } printf("output %x crtc %x\n", output, crtc); @@ -270,9 +323,10 @@ static int drm_find_psvr_xcb(Instance * instance) &output); xcb_randr_create_lease_reply_t *rcl_r = xcb_randr_create_lease_reply(instance->connection, rcl_c, NULL); - if (!rcl_r) { - printf("create_lease failed\n"); - exit(1); + if (!rcl_r) + { + fprintf(stderr, "create_lease failed\n"); + return 0; } int *rcl_f = xcb_randr_create_lease_reply_fds(instance->connection, rcl_r); @@ -299,7 +353,7 @@ bool InitInstance(Instance * instance) } else { - fprintf(stderr, "couldn't find devicee\n"); + fprintf(stderr, "couldn't find device\n"); return false; }