aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/servers/gamma.c139
-rw-r--r--src/types/output.c70
-rw-r--r--src/types/output.h101
3 files changed, 301 insertions, 9 deletions
diff --git a/src/servers/gamma.c b/src/servers/gamma.c
index 0330c51..3eec7ec 100644
--- a/src/servers/gamma.c
+++ b/src/servers/gamma.c
@@ -47,6 +47,8 @@ int handle_get_gamma_info(size_t conn, const char* restrict message_id, const ch
char* restrict buf;
char depth[3];
const char* supported;
+ const char* colourspace;
+ char* gamut[8 * sizeof("White x: 1023")];
size_t n;
if (crtc == NULL) return send_error("protocol error: 'CRTC' header omitted");
@@ -71,6 +73,38 @@ int handle_get_gamma_info(size_t conn, const char* restrict message_id, const ch
default: supported = "maybe"; break;
}
+ switch (output->colourspace)
+ {
+ case COLOURSPACE_SRGB_SANS_GAMUT:
+ case COLOURSPACE_SRGB: colourspace = "Colour space: sRGB\n"; break;
+ case COLOURSPACE_RGB_SANS_GAMUT:
+ case COLOURSPACE_RGB: colourspace = "Colour space: RGB\n"; break;
+ case COLOURSPACE_NON_RGB: colourspace = "Colour space: non-RGB\n"; break;
+ case COLOURSPACE_GREY: colourspace = "Colour space: grey\n"; break;
+ default: colourspace = ""; break;
+ }
+
+ switch (output->colourspace)
+ {
+ case COLOURSPACE_SRGB:
+ case COLOURSPACE_RGB:
+ sprintf(gamut,
+ "Red x: %u\n"
+ "Red y: %u\n"
+ "Green x: %u\n"
+ "Green y: %u\n"
+ "Blue x: %u\n"
+ "Blue y: %u\n"
+ "White x: %u\n"
+ "White y: %u\n",
+ output->red_x, output->red_y, output->green_x, output->green_y,
+ output->blue_x, output->blue_y, output->white_x, output->white_y);
+ break;
+ default:
+ *gamut = '\0';
+ break;
+ }
+
MAKE_MESSAGE(&buf, &n, 0,
"In response to: %s\n"
"Cooperative: yes\n" /* In mds: say ‘no’, mds-coopgamma changes to ‘yes’.” */
@@ -79,9 +113,10 @@ int handle_get_gamma_info(size_t conn, const char* restrict message_id, const ch
"Green size: %zu\n"
"Blue size: %zu\n"
"Gamma support: %s\n"
+ "%s%s"
"\n",
message_id, depth, output->red_size, output->green_size,
- output->blue_size, supported);
+ output->blue_size, supported, gamut, colourspace);
return send_message(conn, buf, n);
}
@@ -116,6 +151,90 @@ void set_gamma(const struct output* restrict output, const union gamma_ramps* re
}
+/**
+ * Parse the EDID of a monitor
+ *
+ * @param output The output
+ */
+static void parse_edid(struct output* restrict output)
+{
+ const unsigned char* restrict edid = (const unsigned char*)(output->name);
+ size_t i;
+ unsigned char sum;
+ int analogue;
+
+ output->red_x = output->green_x = output->blue_x = output->white_x = 0;
+ output->red_y = output->green_y = output->blue_y = output->white_y = 0;
+
+ if (output->name_is_edid == 0)
+ {
+ output->colourspace = COLOURSPACE_UNKNOWN;
+ return;
+ }
+
+ if (strlen(edid) < 128)
+ return;
+ for (i = 0, sum = 0; i < 128; i++)
+ sum += edid[i];
+ if (sum != 0)
+ return;
+ if ((edid[0] != 0) || (edid[7] != 0))
+ return;
+ for (i = 1; i < 7; i++)
+ if (edid[i] != 0xFF)
+ return;
+
+ analogue = !(edid[20] & 0x80);
+ if (!analogue)
+ output->colourspace = COLOURSPACE_RGB;
+ else
+ switch ((edid[24] >> 3) & 3)
+ {
+ case 0: output->colourspace = COLOURSPACE_GREY; break;
+ case 1: output->colourspace = COLOURSPACE_RGB; break;
+ case 2: output->colourspace = COLOURSPACE_NON_RGB; break;
+ default: output->colourspace = COLOURSPACE_UNKNOWN; break;
+ }
+
+ if (output->colourspace != COLOURSPACE_RGB)
+ return;
+
+ if (edid[24] & 2)
+ output->colourspace = COLOURSPACE_SRGB;
+
+ output->red_x = (edid[25] >> 6) & 3;
+ output->red_y = (edid[25] >> 4) & 3;
+ output->green_x = (edid[25] >> 2) & 3;
+ output->green_y = (edid[25] >> 0) & 3;
+ output->blue_x = (edid[26] >> 6) & 3;
+ output->blue_y = (edid[26] >> 4) & 3;
+ output->white_x = (edid[26] >> 2) & 3;
+ output->white_y = (edid[26] >> 0) & 3;
+
+ output->red_x |= ((unsigned)(edid[27])) << 2;
+ output->red_y |= ((unsigned)(edid[28])) << 2;
+ output->green_x |= ((unsigned)(edid[29])) << 2;
+ output->green_y |= ((unsigned)(edid[30])) << 2;
+ output->blue_x |= ((unsigned)(edid[31])) << 2;
+ output->blue_y |= ((unsigned)(edid[32])) << 2;
+ output->white_x |= ((unsigned)(edid[33])) << 2;
+ output->white_y |= ((unsigned)(edid[34])) << 2;
+
+ if ((output->red_x == output->red_y) &&
+ (output->red_x == output->green_x) &&
+ (output->red_x == output->green_y) &&
+ (output->red_x == output->blue_x) &&
+ (output->red_x == output->blue_y) &&
+ (output->red_x == output->white_x) &&
+ (output->red_x == output->white_y))
+ {
+ if (output->colourspace == COLOURSPACE_SRGB)
+ output->colourspace = COLOURSPACE_SRGB_SANS_GAMUT;
+ else
+ output->colourspace = COLOURSPACE_RGB_SANS_GAMUT;
+ }
+}
+
/**
* Store all current gamma ramps
@@ -135,17 +254,18 @@ int initialise_gamma_info(void)
LIBGAMMA_CRTC_INFO_MACRO_RAMP |
LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT |
LIBGAMMA_CRTC_INFO_CONNECTOR_NAME);
- outputs[i].depth = info.gamma_depth_error ? 0 : info.gamma_depth;
- outputs[i].red_size = info.gamma_size_error ? 0 : info.red_gamma_size;
- outputs[i].green_size = info.gamma_size_error ? 0 : info.green_gamma_size;
- outputs[i].blue_size = info.gamma_size_error ? 0 : info.blue_gamma_size;
- outputs[i].supported = info.gamma_support_error ? 0 : info.gamma_support;
+ outputs[i].depth = info.gamma_depth_error ? 0 : info.gamma_depth;
+ outputs[i].red_size = info.gamma_size_error ? 0 : info.red_gamma_size;
+ outputs[i].green_size = info.gamma_size_error ? 0 : info.green_gamma_size;
+ outputs[i].blue_size = info.gamma_size_error ? 0 : info.blue_gamma_size;
+ outputs[i].supported = info.gamma_support_error ? 0 : info.gamma_support;
if (outputs[i].depth == 0 || outputs[i].red_size == 0 ||
outputs[i].green_size == 0 || outputs[i].blue_size == 0)
- outputs[i].supported = 0;
- outputs[i].name = get_crtc_name(&info, crtcs + i);
+ outputs[i].supported = 0;
+ outputs[i].name = get_crtc_name(&info, crtcs + i);
saved_errno = errno;
- outputs[i].crtc = crtcs + i;
+ outputs[i].name_is_edid = ((info.edid_error == 0) && (info.edid != NULL));
+ outputs[i].crtc = crtcs + i;
libgamma_crtc_information_destroy(&info);
outputs[i].ramps_size = outputs[i].red_size + outputs[i].green_size + outputs[i].blue_size;
switch (outputs[i].depth)
@@ -163,6 +283,7 @@ int initialise_gamma_info(void)
errno = saved_errno;
if (outputs[i].name == NULL)
return -1;
+ parse_edid(outputs + i);
}
return 0;
diff --git a/src/types/output.c b/src/types/output.c
index 8576baa..80f3d36 100644
--- a/src/types/output.c
+++ b/src/types/output.c
@@ -125,6 +125,46 @@ size_t output_marshal(const struct output* restrict this, void* restrict buf)
*(enum libgamma_decision*)(bs + off) = this->supported;
off += sizeof(enum libgamma_decision);
+ if (bs != NULL)
+ *(enum colourspace*)(bs + off) = this->colourspace;
+ off += sizeof(enum colourspace);
+
+ if (bs != NULL)
+ *(int*)(bs + off) = this->name_is_edid;
+ off += sizeof(int);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->red_x;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->red_y;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->green_x;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->green_y;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->blue_x;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->blue_y;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->white_x;
+ off += sizeof(unsigned);
+
+ if (bs != NULL)
+ *(unsigned*)(bs + off) = this->white_y;
+ off += sizeof(unsigned);
+
n = strlen(this->name) + 1;
if (bs != NULL)
memcpy(bs + off, this->name, n);
@@ -179,6 +219,36 @@ size_t output_unmarshal(struct output* restrict this, const void* restrict buf)
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)
diff --git a/src/types/output.h b/src/types/output.h
index f8a4c3e..95270ae 100644
--- a/src/types/output.h
+++ b/src/types/output.h
@@ -55,6 +55,49 @@
/**
+ * Colour spaces
+ */
+enum colourspace
+{
+ /**
+ * sRGB with explicit gamut
+ */
+ COLOURSPACE_SRGB = 0,
+
+ /**
+ * sRGB without explicit gamut
+ */
+ COLOURSPACE_SRGB_SANS_GAMUT = 1,
+
+ /**
+ * RGB (but not sRGB) with known gamut
+ */
+ COLOURSPACE_RGB = 2,
+
+ /**
+ * RGB (but not sRGB) without known gamut
+ */
+ COLOURSPACE_RGB_SANS_GAMUT = 3,
+
+ /**
+ * Non-RGB multicolour
+ */
+ COLOURSPACE_NON_RGB = 4,
+
+ /**
+ * Greyscale or monochrome
+ */
+ COLOURSPACE_GREY = 5,
+
+ /**
+ * Unknown
+ */
+ COLOURSPACE_UNKNOWN = 6
+};
+
+
+
+/**
* Information about an output
*/
struct output
@@ -75,6 +118,64 @@ struct output
enum libgamma_decision supported;
/**
+ * Whether the name is the EDID
+ */
+ int name_is_edid;
+
+ /**
+ * The monitor's colour space
+ */
+ enum colourspace colourspace;
+
+ /**
+ * The x-value (CIE xyY) of the monitor's
+ * red colour, multiplied by 1024
+ */
+ unsigned red_x;
+
+ /**
+ * The y-value (CIE xyY) of the monitor's
+ * red colour, multiplied by 1024
+ */
+ unsigned red_y;
+
+ /**
+ * The x-value (CIE xyY) of the monitor's
+ * green colour, multiplied by 1024
+ */
+ unsigned green_x;
+
+ /**
+ * The y-value (CIE xyY) of the monitor's
+ * green colour, multiplied by 1024
+ */
+ unsigned green_y;
+
+ /**
+ * The x-value (CIE xyY) of the monitor's
+ * blue colour, multiplied by 1024
+ */
+ unsigned blue_x;
+
+ /**
+ * The y-value (CIE xyY) of the monitor's
+ * blue colour, multiplied by 1024
+ */
+ unsigned blue_y;
+
+ /**
+ * The x-value (CIE xyY) of the monitor's
+ * default white point, multiplied by 1024
+ */
+ unsigned white_x;
+
+ /**
+ * The y-value (CIE xyY) of the monitor's
+ * default white point, multiplied by 1024
+ */
+ unsigned white_y;
+
+ /**
* The number of stops in the red gamma ramp
*/
size_t red_size;