diff --git a/drm.c b/drm.c index e1d7284..26f8ead 100644 --- a/drm.c +++ b/drm.c @@ -158,7 +158,7 @@ void drm_cleanup() { if (kmsvnc->drm->gamma && kmsvnc->drm->gamma->size && kmsvnc->drm->gamma->red && kmsvnc->drm->gamma->green && kmsvnc->drm->gamma->blue) { if (drmModeCrtcSetGamma(kmsvnc->drm->drm_master_fd ?: kmsvnc->drm->drm_fd, kmsvnc->drm->plane->crtc_id, kmsvnc->drm->gamma->size, kmsvnc->drm->gamma->red, kmsvnc->drm->gamma->green, kmsvnc->drm->gamma->blue)) perror("Failed to restore gamma"); } - if (kmsvnc->drm->gamma->red) { + if (kmsvnc->drm->gamma && kmsvnc->drm->gamma->red) { free(kmsvnc->drm->gamma->red); kmsvnc->drm->gamma->red = kmsvnc->drm->gamma->green = kmsvnc->drm->gamma->blue = NULL; } @@ -474,6 +474,14 @@ int drm_open() { { KMSVNC_FATAL("card %s open failed: %s\n", kmsvnc->card, strerror(errno)); } + if (kmsvnc->screen_blank && !drmIsMaster(drm->drm_fd)) { + drm->drm_master_fd = drm_get_master_fd(); + drm->drm_master_fd = drm->drm_master_fd > 0 ? drm->drm_master_fd : 0; + if (kmsvnc->debug_enabled) { + fprintf(stderr, "not master client, master fd %d\n", drm->drm_master_fd); + } + } + drm->drm_ver = drmGetVersion(drm->drm_fd); printf("drm driver is %s\n", drm->drm_ver->name); @@ -485,65 +493,64 @@ int drm_open() { if (drm_refresh_planes(1)) return 1; - drm->gamma = malloc(sizeof(struct kmsvnc_drm_gamma_data)); - if (!drm->gamma) KMSVNC_FATAL("memory allocation error at %s:%d\n", __FILE__, __LINE__); - memset(drm->gamma, 0, sizeof(struct kmsvnc_drm_gamma_data)); - drmModeCrtc *target_crtc = drmModeGetCrtc(drm->drm_fd, drm->plane->crtc_id); - if (target_crtc) { - if (!drmIsMaster(drm->drm_fd)) { - drm->drm_master_fd = drm_get_master_fd(); - drm->drm_master_fd = drm->drm_master_fd > 0 ? drm->drm_master_fd : 0; - if (kmsvnc->debug_enabled) { - fprintf(stderr, "not master client, master fd %d\n", drm->drm_master_fd); + if (kmsvnc->screen_blank) { + drm->gamma = malloc(sizeof(struct kmsvnc_drm_gamma_data)); + if (!drm->gamma) KMSVNC_FATAL("memory allocation error at %s:%d\n", __FILE__, __LINE__); + memset(drm->gamma, 0, sizeof(struct kmsvnc_drm_gamma_data)); + drmModeCrtc *target_crtc = drmModeGetCrtc(drm->drm_fd, drm->plane->crtc_id); + if (target_crtc) { + drm->gamma->size = (uint32_t)target_crtc->gamma_size; + drm->gamma->red = malloc(drm->gamma->size*sizeof(uint16_t)*3); + if (!drm->gamma->size) { + fprintf(stderr, "drm->gamma->size = %u, not setting gamma.\n", drm->gamma->size); } - } - drm->gamma->size = (uint32_t)target_crtc->gamma_size; - drm->gamma->red = malloc(drm->gamma->size*sizeof(uint16_t)*3); - if (!drm->gamma->size) { - fprintf(stderr, "drm->gamma->size = %u, not setting gamma.\n", drm->gamma->size); - } - else if (!drm->gamma->red) { - fprintf(stderr, "memory allocation error at %s:%d\n", __FILE__, __LINE__); - fprintf(stderr, "not setting gamma.\n"); - } - else { - memset(drm->gamma->red, 0, drm->gamma->size*sizeof(uint16_t)*3); - drm->gamma->green = drm->gamma->red + drm->gamma->size; - drm->gamma->blue = drm->gamma->red + drm->gamma->size*2; - // legacy api, but weston also uses this, so whatever - drmModeCrtcGetGamma(drm->drm_fd, drm->plane->crtc_id, drm->gamma->size, drm->gamma->red, drm->gamma->green, drm->gamma->blue); - if (kmsvnc->debug_enabled) { - for (int i = 0; i < drm->gamma->size; i++) { - fprintf(stderr, "gamma: %05d %05hu %05hu %05hu\n", i, drm->gamma->red[i], drm->gamma->green[i], drm->gamma->blue[i]); - } - } - uint32_t new_gamma_size = drm->gamma->size; - uint16_t *new_gammas = malloc(new_gamma_size*sizeof(uint16_t)*3); - if (!new_gammas) { + else if (!drm->gamma->red) { fprintf(stderr, "memory allocation error at %s:%d\n", __FILE__, __LINE__); fprintf(stderr, "not setting gamma.\n"); } else { - memset(new_gammas, 0, new_gamma_size*sizeof(uint16_t)*3); - if (drmModeCrtcSetGamma(drm->drm_master_fd ?: drm->drm_fd, drm->plane->crtc_id, new_gamma_size, new_gammas, new_gammas+new_gamma_size*sizeof(uint16_t), new_gammas+new_gamma_size*sizeof(uint16_t)*2)) perror("Failed to set gamma"); - if (kmsvnc->debug_enabled) { - for (int i = 0; i < new_gamma_size; i++) { - fprintf(stderr, "new gamma: %05d %05hu %05hu %05hu\n", i, new_gammas[i], new_gammas[i+new_gamma_size], new_gammas[i+new_gamma_size*2]); + memset(drm->gamma->red, 0, drm->gamma->size*sizeof(uint16_t)*3); + drm->gamma->green = drm->gamma->red + drm->gamma->size; + drm->gamma->blue = drm->gamma->red + drm->gamma->size*2; + if (kmsvnc->screen_blank_restore) { + int step = 0x10000 / drm->gamma->size; + for (int i = 0; i < drm->gamma->size; i++) { + drm->gamma->red[i] = drm->gamma->green[i] = drm->gamma->blue[i] = step * i; } } - } - if (new_gammas) { - free(new_gammas); - new_gammas = NULL; + else { + // legacy api, but weston also uses this, so whatever + drmModeCrtcGetGamma(drm->drm_fd, drm->plane->crtc_id, drm->gamma->size, drm->gamma->red, drm->gamma->green, drm->gamma->blue); + } + if (kmsvnc->debug_enabled) { + for (int i = 0; i < drm->gamma->size; i++) { + fprintf(stderr, "gamma: %05d %05hu %05hu %05hu\n", i, drm->gamma->red[i], drm->gamma->green[i], drm->gamma->blue[i]); + } + } + uint16_t *new_gamma_red = malloc(drm->gamma->size*sizeof(uint16_t)*3); + if (!new_gamma_red) { + fprintf(stderr, "memory allocation error at %s:%d\n", __FILE__, __LINE__); + fprintf(stderr, "not setting gamma.\n"); + } + else { + memset(new_gamma_red, 0, drm->gamma->size*sizeof(uint16_t)*3); + uint16_t *new_gamma_green = new_gamma_red + drm->gamma->size; + uint16_t *new_gamma_blue = new_gamma_red + drm->gamma->size*2; + if (drmModeCrtcSetGamma(drm->drm_master_fd ?: drm->drm_fd, drm->plane->crtc_id, drm->gamma->size, new_gamma_red, new_gamma_green, new_gamma_blue)) perror("Failed to set gamma"); + } + if (new_gamma_red) { + free(new_gamma_red); + new_gamma_red = NULL; + } } } - } - else { - fprintf(stderr, "Did not get a crtc structure, not setting gamma.\n"); - } - if (target_crtc) { - drmModeFreeCrtc(target_crtc); - target_crtc = NULL; + else { + fprintf(stderr, "Did not get a crtc structure, not setting gamma.\n"); + } + if (target_crtc) { + drmModeFreeCrtc(target_crtc); + target_crtc = NULL; + } } drm->mfb = drmModeGetFB2(drm->drm_fd, drm->plane->fb_id); diff --git a/drm_master.c b/drm_master.c index 7101dec..b924068 100644 --- a/drm_master.c +++ b/drm_master.c @@ -46,7 +46,7 @@ static inline int cmp_fds(pid_t pid, const char *drm_pth) { int fd = atoi(fdlist[n]->d_name); if (fd > 0) { int cloned = clone_fd(pid, fd); - if (cloned > 0 && !drmSetMaster(cloned)) { + if (cloned > 0 && drmIsMaster(cloned)) { ret = cloned; //if (kmsvnc->debug_enabled) { fprintf(stderr, "found drm master pid=%d, fd=%d, cloned=%d\n", pid, fd, cloned); @@ -76,7 +76,7 @@ int drm_get_master_fd() { int count = scandir("/proc", &proclist, NULL, versionsort); int ret = -1; if (count >= 0) { - for (int n = 0; n < count; n++) { + for (int n = count - 1; n > 0; n--) { if (ret == -1 && proclist[n]->d_type == DT_DIR) { pid_t pid = (pid_t)atoi(proclist[n]->d_name); if (pid > 0) { diff --git a/kmsvnc.c b/kmsvnc.c index 17504ba..541e327 100644 --- a/kmsvnc.c +++ b/kmsvnc.c @@ -238,6 +238,8 @@ static struct argp_option kmsvnc_main_options[] = { {"input-height", 0xff07, "0", 0, "Explicitly set input height"}, {"input-offx", 0xff08, "0", 0, "Set input offset of x axis on a multi display system"}, {"input-offy", 0xff09, "0", 0, "Set input offset of y axis on a multi display system"}, + {"screen-blank", 0xff0a, 0, OPTION_ARG_OPTIONAL, "Blank screen with gamma set on crtc"}, + {"screen-blank-restore-linear", 0xff0b, 0, OPTION_ARG_OPTIONAL, "Restore linear values on exit in case of messed up gamma"}, {"wakeup", 'w', 0, OPTION_ARG_OPTIONAL, "Move mouse to wake the system up before start"}, {"disable-input", 'i', 0, OPTION_ARG_OPTIONAL, "Disable uinput"}, {"desktop-name", 'n', "kmsvnc", 0, "Specify vnc desktop name"}, @@ -337,6 +339,12 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { kmsvnc->input_offy = offset_y; } break; + case 0xff0a: + kmsvnc->screen_blank = 1; + break; + case 0xff0b: + kmsvnc->screen_blank_restore = 1; + break; case 'w': kmsvnc->input_wakeup = 1; break; diff --git a/kmsvnc.h b/kmsvnc.h index 630fdfc..1a5c0d1 100644 --- a/kmsvnc.h +++ b/kmsvnc.h @@ -42,6 +42,8 @@ struct kmsvnc_data int input_height; int input_offx; int input_offy; + char screen_blank; + char screen_blank_restore; struct kmsvnc_drm_data *drm; struct kmsvnc_input_data *input; struct kmsvnc_keymap_data *keymap;