diff options
author | Jon Lund Steffensen <jonlst@gmail.com> | 2010-01-01 19:24:01 +0100 |
---|---|---|
committer | Jon Lund Steffensen <jonlst@gmail.com> | 2010-01-01 19:24:01 +0100 |
commit | b61c9d59d7456dc5a4106e5f1e6b767df290d7be (patch) | |
tree | 8ab315b9dac34adbf6ea3aae02c4b2ed43940932 /src/randr.c | |
parent | Update README, NEWS and ChangeLog for 0.3 release. (diff) | |
download | redshift-ng-b61c9d59d7456dc5a4106e5f1e6b767df290d7be.tar.gz redshift-ng-b61c9d59d7456dc5a4106e5f1e6b767df290d7be.tar.bz2 redshift-ng-b61c9d59d7456dc5a4106e5f1e6b767df290d7be.tar.xz |
Reuse X connection when adjusting gamma ramps.
Save gamma ramps when program starts and restore them on exit (only RANDR).
Try both RANDR and VidMode if nothing was specified, otherwise try only the
specified method.
Diffstat (limited to 'src/randr.c')
-rw-r--r-- | src/randr.c | 295 |
1 files changed, 198 insertions, 97 deletions
diff --git a/src/randr.c b/src/randr.c index 99ac9ec..b67484c 100644 --- a/src/randr.c +++ b/src/randr.c @@ -19,169 +19,270 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <xcb/xcb.h> #include <xcb/randr.h> +#include "randr.h" #include "colorramp.h" +#define RANDR_VERSION_MAJOR 1 +#define RANDR_VERSION_MINOR 3 + + int -randr_check_extension() +randr_init(randr_state_t *state, int screen_num) { xcb_generic_error_t *error; /* Open X server connection */ - xcb_connection_t *conn = xcb_connect(NULL, NULL); + int preferred_screen; + state->conn = xcb_connect(NULL, &preferred_screen); + + if (screen_num < 0) screen_num = preferred_screen; /* Query RandR version */ xcb_randr_query_version_cookie_t ver_cookie = - xcb_randr_query_version(conn, 1, 3); + xcb_randr_query_version(state->conn, RANDR_VERSION_MAJOR, + RANDR_VERSION_MINOR); xcb_randr_query_version_reply_t *ver_reply = - xcb_randr_query_version_reply(conn, ver_cookie, &error); + xcb_randr_query_version_reply(state->conn, ver_cookie, &error); if (error) { fprintf(stderr, "RANDR Query Version, error: %d\n", error->error_code); - xcb_disconnect(conn); + xcb_disconnect(state->conn); return -1; } - if (ver_reply->major_version < 1 || ver_reply->minor_version < 3) { + if (ver_reply->major_version < RANDR_VERSION_MAJOR || + ver_reply->minor_version < RANDR_VERSION_MINOR) { fprintf(stderr, "Unsupported RANDR version (%u.%u)\n", ver_reply->major_version, ver_reply->minor_version); free(ver_reply); - xcb_disconnect(conn); + xcb_disconnect(state->conn); return -1; } free(ver_reply); - /* Close connection */ - xcb_disconnect(conn); + /* Get screen */ + const xcb_setup_t *setup = xcb_get_setup(state->conn); + xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); + state->screen = NULL; - return 0; -} + for (int i = 0; iter.rem > 0; i++) { + if (i == screen_num) { + state->screen = iter.data; + break; + } + xcb_screen_next(&iter); + } -static int -randr_crtc_set_temperature(xcb_connection_t *conn, xcb_randr_crtc_t crtc, - int temp, float gamma[3]) -{ - xcb_generic_error_t *error; + if (state->screen == NULL) { + fprintf(stderr, "Screen %i could not be found.\n", + screen_num); + xcb_disconnect(state->conn); + return -1; + } - /* Request size of gamma ramps */ - xcb_randr_get_crtc_gamma_size_cookie_t gamma_size_cookie = - xcb_randr_get_crtc_gamma_size(conn, crtc); - xcb_randr_get_crtc_gamma_size_reply_t *gamma_size_reply = - xcb_randr_get_crtc_gamma_size_reply(conn, gamma_size_cookie, - &error); + /* Get list of CRTCs for the screen */ + xcb_randr_get_screen_resources_current_cookie_t res_cookie = + xcb_randr_get_screen_resources_current(state->conn, + state->screen->root); + xcb_randr_get_screen_resources_current_reply_t *res_reply = + xcb_randr_get_screen_resources_current_reply(state->conn, + res_cookie, + &error); if (error) { - fprintf(stderr, "RANDR Get CRTC Gamma Size, error: %d\n", - error->error_code); + fprintf(stderr, "RANDR Get Screen Resources Current," + " error: %d\n", error->error_code); + xcb_disconnect(state->conn); return -1; } - int gamma_ramp_size = gamma_size_reply->size; + state->crtc_count = res_reply->num_crtcs; + state->crtcs = malloc(state->crtc_count * sizeof(randr_crtc_state_t)); + if (state->crtcs == NULL) { + perror("malloc"); + xcb_disconnect(state->conn); + return -1; + } - free(gamma_size_reply); + xcb_randr_crtc_t *crtcs = + xcb_randr_get_screen_resources_current_crtcs(res_reply); - if (gamma_ramp_size == 0) { - fprintf(stderr, "Gamma ramp size too small: %i\n", - gamma_ramp_size); - return -1; + /* Save CRTC identifier in state */ + for (int i = 0; i < state->crtc_count; i++) { + state->crtcs[i].crtc = crtcs[i]; } - /* Create new gamma ramps */ - uint16_t *gamma_ramps = malloc(3*gamma_ramp_size*sizeof(uint16_t)); - if (gamma_ramps == NULL) abort(); + free(res_reply); - uint16_t *gamma_r = &gamma_ramps[0*gamma_ramp_size]; - uint16_t *gamma_g = &gamma_ramps[1*gamma_ramp_size]; - uint16_t *gamma_b = &gamma_ramps[2*gamma_ramp_size]; + /* Save size and gamma ramps of all CRTCs. + Current gamma ramps are saved so we can restore them + at program exit. */ + for (int i = 0; i < state->crtc_count; i++) { + xcb_randr_crtc_t crtc = state->crtcs[i].crtc; + + /* Request size of gamma ramps */ + xcb_randr_get_crtc_gamma_size_cookie_t gamma_size_cookie = + xcb_randr_get_crtc_gamma_size(state->conn, crtc); + xcb_randr_get_crtc_gamma_size_reply_t *gamma_size_reply = + xcb_randr_get_crtc_gamma_size_reply(state->conn, + gamma_size_cookie, + &error); + + if (error) { + fprintf(stderr, "RANDR Get CRTC Gamma Size," + " error: %d\n", error->error_code); + xcb_disconnect(state->conn); + return -1; + } - colorramp_fill(gamma_r, gamma_g, gamma_b, gamma_ramp_size, - temp, gamma); + unsigned int ramp_size = gamma_size_reply->size; + state->crtcs[i].ramp_size = ramp_size; - /* Set new gamma ramps */ - xcb_void_cookie_t gamma_set_cookie = - xcb_randr_set_crtc_gamma_checked(conn, crtc, gamma_ramp_size, - gamma_r, gamma_g, gamma_b); - error = xcb_request_check(conn, gamma_set_cookie); + free(gamma_size_reply); - if (error) { - fprintf(stderr, "RANDR Set CRTC Gamma, error: %d\n", - error->error_code); - free(gamma_ramps); - return -1; - } + if (ramp_size == 0) { + fprintf(stderr, "Gamma ramp size too small: %i\n", + ramp_size); + xcb_disconnect(state->conn); + return -1; + } + + /* Request current gamma ramps */ + xcb_randr_get_crtc_gamma_cookie_t gamma_get_cookie = + xcb_randr_get_crtc_gamma(state->conn, crtc); + xcb_randr_get_crtc_gamma_reply_t *gamma_get_reply = + xcb_randr_get_crtc_gamma_reply(state->conn, + gamma_get_cookie, + &error); + + if (error) { + fprintf(stderr, "RANDR Get CRTC Gamma, error: %d\n", + error->error_code); + xcb_disconnect(state->conn); + return -1; + } - free(gamma_ramps); + uint16_t *gamma_r = + xcb_randr_get_crtc_gamma_red(gamma_get_reply); + uint16_t *gamma_g = + xcb_randr_get_crtc_gamma_green(gamma_get_reply); + uint16_t *gamma_b = + xcb_randr_get_crtc_gamma_blue(gamma_get_reply); + + /* Allocate space for saved gamma ramps */ + state->crtcs[i].saved_ramps = + malloc(3*ramp_size*sizeof(uint16_t)); + if (state->crtcs[i].saved_ramps == NULL) { + perror("malloc"); + free(gamma_get_reply); + xcb_disconnect(state->conn); + return -1; + } + + /* Copy gamma ramps into CRTC state */ + memcpy(&state->crtcs[i].saved_ramps[0*ramp_size], gamma_r, + ramp_size*sizeof(uint16_t)); + memcpy(&state->crtcs[i].saved_ramps[1*ramp_size], gamma_g, + ramp_size*sizeof(uint16_t)); + memcpy(&state->crtcs[i].saved_ramps[2*ramp_size], gamma_b, + ramp_size*sizeof(uint16_t)); + + free(gamma_get_reply); + } return 0; } -int -randr_set_temperature(int screen_num, int temp, float gamma[3]) +void +randr_restore(randr_state_t *state) { xcb_generic_error_t *error; - /* Open X server connection */ - int preferred_screen; - xcb_connection_t *conn = xcb_connect(NULL, &preferred_screen); - - if (screen_num < 0) screen_num = preferred_screen; - - /* Get screen */ - const xcb_setup_t *setup = xcb_get_setup(conn); - xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); - xcb_screen_t *screen = NULL; - - for (int i = 0; iter.rem > 0; i++) { - if (i == screen_num) { - screen = iter.data; - break; + /* Restore CRTC gamma ramps */ + for (int i = 0; i < state->crtc_count; i++) { + xcb_randr_crtc_t crtc = state->crtcs[i].crtc; + + unsigned int ramp_size = state->crtcs[i].ramp_size; + uint16_t *gamma_r = &state->crtcs[i].saved_ramps[0*ramp_size]; + uint16_t *gamma_g = &state->crtcs[i].saved_ramps[1*ramp_size]; + uint16_t *gamma_b = &state->crtcs[i].saved_ramps[2*ramp_size]; + + /* Set gamma ramps */ + xcb_void_cookie_t gamma_set_cookie = + xcb_randr_set_crtc_gamma_checked(state->conn, crtc, + ramp_size, gamma_r, + gamma_g, gamma_b); + error = xcb_request_check(state->conn, gamma_set_cookie); + + if (error) { + fprintf(stderr, "RANDR Set CRTC Gamma, error: %d\n" + "Unable to restore CRTC %i\n", + error->error_code, i); } - xcb_screen_next(&iter); } +} - if (screen == NULL) { - fprintf(stderr, "Screen %i could not be found.\n", - screen_num); - xcb_disconnect(conn); - return -1; +void +randr_free(randr_state_t *state) +{ + /* Free CRTC state */ + for (int i = 0; i < state->crtc_count; i++) { + free(state->crtcs[i].saved_ramps); } + free(state->crtcs); - /* Get list of CRTCs for the screen */ - xcb_randr_get_screen_resources_current_cookie_t res_cookie = - xcb_randr_get_screen_resources_current(conn, screen->root); - xcb_randr_get_screen_resources_current_reply_t *res_reply = - xcb_randr_get_screen_resources_current_reply(conn, res_cookie, - &error); + /* Close connection */ + xcb_disconnect(state->conn); +} - if (error) { - fprintf(stderr, "RANDR Get Screen Resources Current," - " error: %d\n", error->error_code); - xcb_disconnect(conn); - return -1; - } +int +randr_set_temperature(randr_state_t *state, int temp, float gamma[3]) +{ + xcb_generic_error_t *error; - xcb_randr_crtc_t *crtcs = - xcb_randr_get_screen_resources_current_crtcs(res_reply); + /* Set temperature on all CRTCs */ + for (int i = 0; i < state->crtc_count; i++) { + xcb_randr_crtc_t crtc = state->crtcs[i].crtc; + unsigned int ramp_size = state->crtcs[i].ramp_size; - for (int i = 0; i < res_reply->num_crtcs; i++) { - int r = randr_crtc_set_temperature(conn, crtcs[i], - temp, gamma); - if (r < 0) { - fprintf(stderr, "WARNING: Unable to adjust" - " CRTC %i.\n", i); + /* Create new gamma ramps */ + uint16_t *gamma_ramps = malloc(3*ramp_size*sizeof(uint16_t)); + if (gamma_ramps == NULL) { + perror("malloc"); + return -1; } - } - free(res_reply); + uint16_t *gamma_r = &gamma_ramps[0*ramp_size]; + uint16_t *gamma_g = &gamma_ramps[1*ramp_size]; + uint16_t *gamma_b = &gamma_ramps[2*ramp_size]; + + colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size, + temp, gamma); + + /* Set new gamma ramps */ + xcb_void_cookie_t gamma_set_cookie = + xcb_randr_set_crtc_gamma_checked(state->conn, crtc, + ramp_size, gamma_r, + gamma_g, gamma_b); + error = xcb_request_check(state->conn, gamma_set_cookie); + + if (error) { + fprintf(stderr, "RANDR Set CRTC Gamma, error: %d\n", + error->error_code); + free(gamma_ramps); + return -1; + } - /* Close connection */ - xcb_disconnect(conn); + free(gamma_ramps); + } return 0; } |