aboutsummaryrefslogtreecommitdiffstats
path: root/types-output.c
diff options
context:
space:
mode:
Diffstat (limited to 'types-output.c')
-rw-r--r--types-output.c322
1 files changed, 322 insertions, 0 deletions
diff --git a/types-output.c b/types-output.c
new file mode 100644
index 0000000..e3296cc
--- /dev/null
+++ b/types-output.c
@@ -0,0 +1,322 @@
+/* See LICENSE file for copyright and license details. */
+#include "types-output.h"
+#include "util.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/**
+ * Free all resources allocated to an output.
+ * The allocation of `output` itself is not freed,
+ * nor is its the libgamma destroyed.
+ *
+ * @param this The output
+ */
+void
+output_destroy(struct output *restrict this)
+{
+ size_t i;
+
+ if (this->supported != LIBGAMMA_NO) {
+ switch (this->depth) {
+ case 8:
+ libgamma_gamma_ramps8_destroy(&this->saved_ramps.u8);
+ for (i = 0; i < this->table_size; i++)
+ libgamma_gamma_ramps8_destroy(&this->table_sums[i].u8);
+ break;
+
+ case 16:
+ libgamma_gamma_ramps16_destroy(&this->saved_ramps.u16);
+ for (i = 0; i < this->table_size; i++)
+ libgamma_gamma_ramps16_destroy(&this->table_sums[i].u16);
+ break;
+
+ case 32:
+ libgamma_gamma_ramps32_destroy(&this->saved_ramps.u32);
+ for (i = 0; i < this->table_size; i++)
+ libgamma_gamma_ramps32_destroy(&this->table_sums[i].u32);
+ break;
+
+ case 64:
+ libgamma_gamma_ramps64_destroy(&this->saved_ramps.u64);
+ for (i = 0; i < this->table_size; i++)
+ libgamma_gamma_ramps64_destroy(&this->table_sums[i].u64);
+ break;
+
+ case -1:
+ libgamma_gamma_rampsf_destroy(&this->saved_ramps.f);
+ for (i = 0; i < this->table_size; i++)
+ libgamma_gamma_rampsf_destroy(&this->table_sums[i].f);
+ break;
+
+ case -2:
+ libgamma_gamma_rampsd_destroy(&this->saved_ramps.d);
+ for (i = 0; i < this->table_size; i++)
+ libgamma_gamma_rampsd_destroy(&this->table_sums[i].d);
+ break;
+
+ default:
+ break; /* impossible */
+ }
+ }
+
+ for (i = 0; i < this->table_size; i++)
+ filter_destroy(&this->table_filters[i]);
+
+ free(this->table_filters);
+ free(this->table_sums);
+ free(this->name);
+}
+
+
+#if defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wcast-align"
+#endif
+
+
+/**
+ * Marshal an output
+ *
+ * @param this The output
+ * @param buf Output buffer for the marshalled output,
+ * `NULL` just measure how large the buffers
+ * needs to be
+ * @return The number of marshalled byte
+ */
+size_t
+output_marshal(const struct output *restrict this, void *restrict buf)
+{
+ size_t off = 0, i, n;
+ char *bs = buf;
+
+ if (bs)
+ *(signed *)&bs[off] = this->depth;
+ off += sizeof(signed);
+
+ if (bs)
+ *(size_t *)&bs[off] = this->red_size;
+ off += sizeof(size_t);
+
+ if (bs)
+ *(size_t *)&bs[off] = this->green_size;
+ off += sizeof(size_t);
+
+ if (bs)
+ *(size_t *)&bs[off] = this->blue_size;
+ off += sizeof(size_t);
+
+ if (bs)
+ *(size_t *)&bs[off] = this->ramps_size;
+ off += sizeof(size_t);
+
+ if (bs)
+ *(enum libgamma_decision *)&bs[off] = this->supported;
+ off += sizeof(enum libgamma_decision);
+
+ if (bs)
+ *(enum colourspace *)&bs[off] = this->colourspace;
+ off += sizeof(enum colourspace);
+
+ if (bs)
+ *(int *)&bs[off] = this->name_is_edid;
+ off += sizeof(int);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->red_x;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->red_y;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->green_x;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->green_y;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->blue_x;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->blue_y;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->white_x;
+ off += sizeof(unsigned);
+
+ if (bs)
+ *(unsigned *)&bs[off] = this->white_y;
+ off += sizeof(unsigned);
+
+ n = strlen(this->name) + 1;
+ if (bs)
+ memcpy(&bs[off], this->name, n);
+ off += n;
+
+ off += gamma_ramps_marshal(&(this->saved_ramps), bs ? &bs[off] : NULL, this->ramps_size);
+
+ if (bs)
+ *(size_t *)&bs[off] = this->table_size;
+ off += sizeof(size_t);
+
+ for (i = 0; i < this->table_size; i++) {
+ off += filter_marshal(this->table_filters + i, bs ? &bs[off] : NULL, this->ramps_size);
+ off += gamma_ramps_marshal(this->table_sums + i, bs ? &bs[off] : NULL, this->ramps_size);
+ }
+
+ return off;
+}
+
+
+/**
+ * Unmarshal an output
+ *
+ * @param this Output for the output
+ * @param buf Buffer with the marshalled output
+ * @return The number of unmarshalled bytes, 0 on error
+ */
+size_t
+output_unmarshal(struct output *restrict this, const void *restrict buf)
+{
+ size_t off = 0, i, n;
+ const char *bs = buf;
+
+ this->crtc = NULL;
+ this->name = NULL;
+
+ this->depth = *(const signed *)&bs[off];
+ off += sizeof(signed);
+
+ this->red_size = *(const size_t *)&bs[off];
+ off += sizeof(size_t);
+
+ this->green_size = *(const size_t *)&bs[off];
+ off += sizeof(size_t);
+
+ this->blue_size = *(const size_t *)&bs[off];
+ off += sizeof(size_t);
+
+ this->ramps_size = *(const size_t *)&bs[off];
+ off += sizeof(size_t);
+
+ this->supported = *(const enum libgamma_decision *)&bs[off];
+ off += sizeof(enum libgamma_decision);
+
+ this->colourspace = *(const enum colourspace *)&bs[off];
+ off += sizeof(enum colourspace);
+
+ this->name_is_edid = *(const int *)&bs[off];
+ off += sizeof(int);
+
+ this->red_x = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->red_y = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->green_x = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->green_y = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->blue_x = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->blue_y = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->white_x = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ this->white_y = *(const unsigned *)&bs[off];
+ off += sizeof(unsigned);
+
+ n = strlen(&bs[off]) + 1;
+ this->name = memdup(&bs[off], n);
+ if (this->name == NULL)
+ return 0;
+ off += n;
+
+ COPY_RAMP_SIZES(&this->saved_ramps.u8, this);
+ off += n = gamma_ramps_unmarshal(&this->saved_ramps, &bs[off], this->ramps_size);
+ if (n == 0)
+ return 0;
+
+ this->table_size = this->table_alloc = *(const size_t*)&bs[off];
+ off += sizeof(size_t);
+ if (this->table_size > 0) {
+ this->table_filters = calloc(this->table_size, sizeof(*this->table_filters));
+ if (!this->table_filters)
+ return 0;
+ this->table_sums = calloc(this->table_size, sizeof(*this->table_sums));
+ if (!this->table_sums)
+ return 0;
+ }
+
+ for (i = 0; i < this->table_size; i++) {
+ off += n = filter_unmarshal(&this->table_filters[i], &bs[off], this->ramps_size);
+ if (!n)
+ return 0;
+ COPY_RAMP_SIZES(&this->table_sums[i].u8, this);
+ off += n = gamma_ramps_unmarshal(&this->table_sums[i], &bs[off], this->ramps_size);
+ if (!n)
+ return 0;
+ }
+
+ return off;
+}
+
+
+#if defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
+
+
+/**
+ * Compare to outputs by the names of their respective CRTC:s
+ *
+ * @param a Return -1 if this one is lower
+ * @param b Return +1 if this one is higher
+ * @return See description of `a` and `b`,
+ * 0 if returned if they are the same
+ */
+int
+output_cmp_by_name(const void *restrict a, const void *restrict b)
+{
+ const struct output *x = a, *y = b;
+ return strcmp(x->name, y->name);
+}
+
+
+/**
+ * Find an output by its name
+ *
+ * @param key The name of the output
+ * @param base The array of outputs
+ * @param n The number of elements in `base`
+ * @return Output find in `base`, `NULL` if not found
+ */
+struct output *
+output_find_by_name(const char *restrict key, struct output *restrict base, size_t n)
+{
+ struct output k;
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+ k.name = (char *)key;
+#if defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
+ return bsearch(&k, base, n, sizeof(*base), output_cmp_by_name);
+}