aboutsummaryrefslogtreecommitdiffstats
path: root/src/cg-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cg-base.c')
-rw-r--r--src/cg-base.c275
1 files changed, 247 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: