diff options
| author | Mattias Andrée <maandree@kth.se> | 2016-08-04 17:43:24 +0200 | 
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2016-08-04 17:43:24 +0200 | 
| commit | 2806d5f7e1b5223d5b8524ae4770235fc69aa85b (patch) | |
| tree | 99b2cb5264b682807e7c2288809b84754761e8ea | |
| parent | m (diff) | |
| download | cg-tools-2806d5f7e1b5223d5b8524ae4770235fc69aa85b.tar.gz cg-tools-2806d5f7e1b5223d5b8524ae4770235fc69aa85b.tar.bz2 cg-tools-2806d5f7e1b5223d5b8524ae4770235fc69aa85b.tar.xz | |
Work on cg-base
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | src/cg-base.c | 275 | ||||
| -rw-r--r-- | src/cg-base.h | 80 | 
2 files changed, 327 insertions, 28 deletions
| diff --git a/src/cg-base.c b/src/cg-base.c index 59248c3..6f6f7df 100644 --- a/src/cg-base.c +++ b/src/cg-base.c @@ -47,6 +47,11 @@ libcoopgamma_context_t cg;  char** crtcs = NULL;  /** + * Gamma ramp updates for each CRTC + */ +filter_update_t* crtc_updates = NULL; + +/**   * CRTC and monitor information about   * each selected CRTC and connect monitor   */ @@ -58,6 +63,133 @@ libcoopgamma_crtc_info_t* crtc_info = NULL;  size_t crtcs_n = 0; +/** + * Contexts for asynchronous ramp updates + */ +static libcoopgamma_async_context_t* asyncs = NULL; + +/** + * The number of pending sends + */ +static size_t pending_sends = 0; + +/** + * The number of pending receives + */ +static size_t pending_recvs = 0; + + + +/** + * Data used to sort CRTC:s + */ +struct crtc_sort_data +{ +  /** +   * The gamma ramp type +   */ +  libcoopgamma_depth_t depth; +   +  /** +   * Should be 0 +   */ +  int __padding; +   +  /** +   * The size of the red gamma ramp +   */ +  size_t red_size; +   +  /** +   * The size of the green gamma ramp +   */ +  size_t green_size; +   +  /** +   * The size of the blue gamma ramp +   */ +  size_t blue_size; +   +  /** +   * The index of the CRTC +   */ +  size_t index; +}; + + + +/** + * Compare two instances of `crtc_sort_data` + *  + * @param   a_  Return -1 if this one is lower + * @param   b_  Return +1 if this one is higher + * @return      See `a_` and `b_`, only -1 or +1 can be returned + */ +static int crtc_sort_data_cmp(const void* a_, const void* b_) +{ +  const struct crtc_sort_data* a = a_; +  const struct crtc_sort_data* b = b_; +  int cmp = memcmp(a, b, sizeof(*a) - sizeof(a->index)); +  return cmp ? cmp : a->index < b->index ? -1 : +1; +} + + +/** + * Make elements in `crtc_updates` slaves where appropriate + *  + * @return  Zero on success, -1 on error + */ +int make_slaves(void) +{ +  struct crtc_sort_data* data; +  size_t i, j, master = 0, master_i; +   +  data = alloca(crtcs_n * sizeof(*data)); +  memset(data, 0, crtcs_n * sizeof(*data)); +  for (i = 0; i < crtcs_n; i++) +    { +      data[i].depth      = crtc_updates[i].filter.depth; +      data[i].red_size   = crtc_updates[i].filter.ramps.u8.red_size; +      data[i].green_size = crtc_updates[i].filter.ramps.u8.green_size; +      data[i].blue_size  = crtc_updates[i].filter.ramps.u8.blue_size; +      data[i].index      = i; +    } +   +  qsort(data, crtcs_n, sizeof(*data), crtc_sort_data_cmp); +   +  for (i = 1; i < crtcs_n; i++) +    if (memcmp(data + i, data + master, sizeof(*data) - sizeof(data->index))) +      { +	if (master + 1 < i) +	  { +	    crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); +	    if (crtc_updates[master_i].slaves == NULL) +	      return -1; +	    for (j = 0; master + j < i; j++) +	      crtc_updates[master_i].slaves[j] = data[master + j].index; +	  } +	master = i; +	master_i = data[master].index; +      } +    else +      { +	libcoopgamma_ramps_destroy(&(crtc_updates[data[i].index].filter.ramps.u8)); +	crtc_updates[data[i].index].master = 0; +	crtc_updates[data[i].index].filter.ramps.u8 = crtc_updates[master_i].filter.ramps.u8; +      } +   +  if (master + 1 < i) +    { +      crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); +      if (crtc_updates[master_i].slaves == NULL) +	return -1; +      for (j = 0; master + j < i; j++) +	crtc_updates[master_i].slaves[j] = data[master + j].index; +    } +   +  return 0; +} +  /**   * Initialise the process, specifically @@ -144,16 +276,11 @@ static int list_crtcs(void)  static int get_crtc_info(void)  {    size_t i, unsynced = 0, selected; -  libcoopgamma_async_context_t* async;    char* synced;    int saved_errno, need_flush = 0, fail_rc = -1;    struct pollfd pollfd; -  async = alloca(crtcs_n * sizeof(*async));    synced = alloca(crtcs_n * sizeof(*synced)); -  for (i = 0; i < crtcs_n; i++) -    if (libcoopgamma_async_context_initialise(async + i) < 0) -      return -1;    memset(synced, 0, crtcs_n * sizeof(*synced));    i = 0; @@ -177,7 +304,7 @@ static int get_crtc_info(void)  	    goto send_fail;  	  need_flush = 0;  	  for (; i < crtcs_n; i++) -	    if (unsynced++, libcoopgamma_get_gamma_info_send(crtcs[i], &cg, async + i) < 0) +	    if (unsynced++, libcoopgamma_get_gamma_info_send(crtcs[i], &cg, asyncs + i) < 0)  	      goto send_fail;  	  goto send_done;  	send_fail: @@ -202,14 +329,14 @@ static int get_crtc_info(void)        if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI))  	while (unsynced > 0) -	  switch (libcoopgamma_synchronise(&cg, async, i, &selected)) +	  switch (libcoopgamma_synchronise(&cg, asyncs, i, &selected))  	    {  	    case 0:  	      if (synced[selected])  		break;  	      synced[selected] = 1;  	      unsynced -= 1; -	      if (libcoopgamma_get_gamma_info_recv(crtc_info + selected, &cg, async + selected) < 0) +	      if (libcoopgamma_get_gamma_info_recv(crtc_info + selected, &cg, asyncs + selected) < 0)  		goto cg_fail;  	      break;  	    case -1: @@ -230,16 +357,10 @@ static int get_crtc_info(void)  	    }      } -  for (i = 0; i < crtcs_n; i++) -    libcoopgamma_async_context_destroy(async + i);    return 0;   cg_fail:    fail_rc = -2;   fail: -  saved_errno = errno; -  for (i = 0; i < crtcs_n; i++) -    libcoopgamma_async_context_destroy(async + i); -  errno = saved_errno;    return fail_rc;  } @@ -259,19 +380,26 @@ static int get_crtc_info(void)   *     This option can be used multiple times. If it   *     is not used at all, all CRTC:s will be selected.   *  + * -p PRIORITY + *     Select the priority for the filter, this should + *     be a signed two's-complement integer. If + *     PRIORITY is "?", the default priority for the + *     program is printed to stdout. + *    * @param   argc  The number of command line arguments   * @param   argv  The command line arguments   * @return        0 on success, 1 on error   */  int main(int argc, char* argv[])  { -  int init_failed = 0;    int stage = 0;    int dealloc_crtcs = 0;    int rc = 0;    char* method = NULL;    char* site = NULL;    size_t crtcs_i = 0; +  int64_t priority = default_priority; +  char* prio = NULL;    argv0 = *argv++, argc--; @@ -303,12 +431,12 @@ int main(int argc, char* argv[])  	    arg = argv[1];  	  if (!strcmp(opt, "-m"))  	    { -	      if ((method = arg) == NULL) +	      if ((method != NULL) || ((method = arg) == NULL))  		usage();  	    }  	  else if (!strcmp(opt, "-s"))  	    { -	      if ((site = arg) == NULL) +	      if ((site != NULL) || ((site = arg) == NULL))  		usage();  	    }  	  else if (!strcmp(opt, "-c")) @@ -317,6 +445,11 @@ int main(int argc, char* argv[])  		usage();  	      crtcs[crtcs_i++] = arg;  	    } +	  else if (!strcmp(opt, "-p")) +	    { +	      if ((prio != NULL) || ((prio = arg) == NULL)) +		usage(); +	    }  	  else  	    switch (handle_opt(opt, arg))  	      { @@ -339,6 +472,14 @@ int main(int argc, char* argv[])    if (handle_args(argc, argv, method, site, crtcs) < 0)      goto fail; +  if ((prio != NULL) && !strcmp(prio, "?")) +    { +      printf("%" PRIi64 "\n", priority); +      return 0; +    } +  else if (prio != NULL) +    priority = (int64_t)atoll(prio); +      if ((method != NULL) && !strcmp(method, "?"))      {        if (list_methods() < 0) @@ -351,8 +492,8 @@ int main(int argc, char* argv[])    stage++;    if (libcoopgamma_connect(method, site, &cg) < 0)      { -      init_failed = (errno == 0); -      goto fail; +      fprintf(stderr, "%s: server failed to initialise\n", argv0); +      goto custom_fail;      }    stage++; @@ -377,9 +518,14 @@ int main(int argc, char* argv[])        for (; crtcs[crtcs_n] != NULL; crtcs_n++);      } -  crtc_info = calloc(crtcs_n + 1, sizeof(*crtc_info)); -  if (crtc_info == NULL) -    goto fail; +  if (crtcs_n == 0) +    { +      fprintf(stderr, "%s: no CRTC:s are available\n", argv0); +      goto custom_fail; +    } +   +  crtc_info = alloca(crtcs_n * sizeof(*crtc_info)); +  memset(crtc_info, 0, crtcs_n * sizeof(*crtc_info));    for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++)      if (libcoopgamma_crtc_info_initialise(crtc_info + crtcs_i) < 0)        goto cg_fail; @@ -387,6 +533,56 @@ int main(int argc, char* argv[])    if (libcoopgamma_set_nonblocking(&cg, 1) < 0)      goto fail; +  asyncs = alloca(crtcs_n * sizeof(*asyncs)); +  memset(asyncs, 0, crtcs_n * sizeof(*asyncs)); +  for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++) +    if (libcoopgamma_async_context_initialise(asyncs + crtcs_i) < 0) +      goto fail; +   +  crtc_updates = alloca(crtcs_n * sizeof(*crtc_updates)); +  memset(crtc_updates, 0, crtcs_n * sizeof(*crtc_updates)); +  for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++) +    { +      if (libcoopgamma_filter_initialise(&(crtc_updates[crtcs_i].filter)) < 0) +	goto fail; +      if (libcoopgamma_error_initialise(&(crtc_updates[crtcs_i].error)) < 0) +	goto fail; +      crtc_updates[crtcs_i].synced = 1; +      crtc_updates[crtcs_i].failed = 0; +      crtc_updates[crtcs_i].master = 1; +      crtc_updates[crtcs_i].slaves = NULL; +      crtc_updates[crtcs_i].filter.crtc                = crtcs[crtcs_i]; +      crtc_updates[crtcs_i].filter.priority            = priority; +      crtc_updates[crtcs_i].filter.depth               = crtc_info[crtcs_i].depth; +      crtc_updates[crtcs_i].filter.ramps.u8.red_size   = crtc_info[crtcs_i].red_size; +      crtc_updates[crtcs_i].filter.ramps.u8.green_size = crtc_info[crtcs_i].green_size; +      crtc_updates[crtcs_i].filter.ramps.u8.blue_size  = crtc_info[crtcs_i].blue_size; +      switch (crtc_updates[crtcs_i].filter.depth) +	{ +	case LIBCOOPGAMMA_UINT8: +	  libcoopgamma_ramps_initialise(&(crtc_updates[crtcs_i].filter.ramps.u8)); +	  break; +	case LIBCOOPGAMMA_UINT16: +	  libcoopgamma_ramps_initialise(&(crtc_updates[crtcs_i].filter.ramps.u16)); +	  break; +	case LIBCOOPGAMMA_UINT32: +	  libcoopgamma_ramps_initialise(&(crtc_updates[crtcs_i].filter.ramps.u32)); +	  break; +	case LIBCOOPGAMMA_UINT64: +	  libcoopgamma_ramps_initialise(&(crtc_updates[crtcs_i].filter.ramps.u64)); +	  break; +	case LIBCOOPGAMMA_FLOAT: +	  libcoopgamma_ramps_initialise(&(crtc_updates[crtcs_i].filter.ramps.f)); +	  break; +	case LIBCOOPGAMMA_DOUBLE: +	  libcoopgamma_ramps_initialise(&(crtc_updates[crtcs_i].filter.ramps.d)); +	  break; +	default: +	  fprintf(stderr, "%s: internal error: gamma ramp type is unrecognised\n", argv0); +	  goto custom_fail; +	} +    } +      switch (get_crtc_info())      {      case 0: @@ -397,7 +593,17 @@ int main(int argc, char* argv[])        goto cg_fail;      } -  /* TODO start */ +  switch (start()) +    { +    case 0: +      break; +    case -1: +      goto fail; +    case -2: +      goto cg_fail; +    case -3: +      goto custom_fail; +    }   done:    if (dealloc_crtcs) @@ -405,17 +611,30 @@ int main(int argc, char* argv[])    if (crtc_info != NULL)      for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++)        libcoopgamma_crtc_info_destroy(crtc_info + crtcs_i); -  free(crtc_info); +  if (asyncs != NULL) +    for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++) +      libcoopgamma_async_context_destroy(asyncs + crtcs_i);    if (stage >= 1)      libcoopgamma_context_destroy(&cg, stage >= 2); +  if (crtc_updates != NULL) +    for (crtcs_i = 0; crtcs_i < crtcs_n; crtcs_i++) +      { +	if (crtc_updates[crtcs_i].master == 0) +	  memset(&(crtc_updates[crtcs_i].filter.ramps.u8), 0, sizeof(crtc_updates[crtcs_i].filter.ramps.u8)); +	crtc_updates[crtcs_i].filter.crtc = NULL; +	libcoopgamma_filter_destroy(&(crtc_updates[crtcs_i].filter)); +	libcoopgamma_error_destroy(&(crtc_updates[crtcs_i].error)); +	free(crtc_updates[crtcs_i].slaves); +      }    return rc; + custom_fail: +  rc = 1; +  goto done; +     fail:    rc = 1; -  if (init_failed) -    fprintf(stderr, "%s: server failed to initialise\n", argv0); -  else -    perror(argv0); +  perror(argv0);    goto done;   cg_fail: diff --git a/src/cg-base.h b/src/cg-base.h index 662f044..13667b7 100644 --- a/src/cg-base.h +++ b/src/cg-base.h @@ -20,6 +20,55 @@  /** + * Information (except asynchronous call context) + * required to update the gamma ramps on a CRTC. + */ +typedef struct filter_update +{ +  /** +   * The filter to update +   *  +   * `.filter.crtc` and `.filter.priority` +   * are preconfigured +   */ +  libcoopgamma_filter_t filter; +   +  /** +   * Has the update been synchronised? +   */ +  int synced; +   +  /** +   * Did the update fail? +   */ +  int failed; +   +  /** +   * Error description if `.failed` is true +   */ +  libcoopgamma_error_t error; +   +  /** +   * If zero, the ramps in `.filter` shall +   * neither be modified nor freed. +   */ +  int master; +   +  /** +   * 0-terminated list of elements in +   * `.crtc_updates` which shares gamma +   * ramps with this instance +   *  +   * This will only be set if `.master` +   * is true. +   */ +  size_t* slaves; +   +} filter_update_t; + + + +/**   * The process's name   */  extern const char* argv0; @@ -35,6 +84,11 @@ extern libcoopgamma_context_t cg;  extern char** crtcs;  /** + * Gamma ramp updates for each CRTC + */ +extern filter_update_t* crtc_updates; + +/**   * CRTC and monitor information about   * each selected CRTC and connect monitor   */ @@ -48,6 +102,22 @@ extern size_t crtcs_n;  /** + * The default filter priority for the program + */ +extern const int64_t default_priority; + + + +/** + * Make elements in `crtc_updates` slaves where appropriate + *  + * @return  Zero on success, -1 on error + */ +int make_slaves(void); + + + +/**   * Print usage information and exit   */  #if defined(__GNUC__) @@ -90,3 +160,13 @@ __attribute__((__nonnull__(2)))  #endif  extern int handle_args(int argc, char* argv[], char* method, char* site, char** crtcs); +/** + * The main function for the program-specific code + *  + * @return  0: Success + *          -1: Error, `errno` set + *          -2: Error, `cg.error` set + *          -3: Error, message already printed + */ +extern int start(void); + | 
